Ticket #1449: 1449_rms_wall_overlap6_comments.patch

File 1449_rms_wall_overlap6_comments.patch, 39.3 KB (added by vts, 12 years ago)

Some comments on the RMS wall builder

  • binaries/data/mods/public/maps/random/rmgen/library.js

     
    331331    }
    332332}
    333333
     334/**
     335 * Placed an entity with template "type" belonging to the given player at the specified X/Z location (in world units),
     336 * and with the given rotation angle.
     337 * 
     338 * @param type    Template name of the entity to be placed
     339 * @param player  Owning player ID
     340 * @param angle   TODO: document convention used for this angle
     341 */
    334342function placeObject(x, z, type, player, angle)
    335343{
    336344    g_Map.addObject(new Entity(type, player, x, z, angle));
  • binaries/data/mods/public/maps/random/rmgen/wall_builder.js

     
    3333// ?Think of something to enable splitting walls into two walls so more complex walls can be build and roads can have branches/crossroads?
    3434// ?Readjust placement angle for wall elements with bending when used in linear/circular walls by their bending?
    3535
     36/**
     37 * Note: this library uses its own coordinate system conventions and nomenclature that may not necessarily match those used in the rest of the game.
     38 * Refer to http://trac.wildfiregames.com/wiki/Rmgen_Library for documentation.
     39 */
    3640
    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 droppoints right (in rmgen)
    41 //  The coure 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 enlengthens 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 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     41/**
     42 * WallElement constructor.
     43 *
     44 * Defines a type of wall element, i.e. entities that are atomic parts of a wall. Walls are conceptualized as a sequence of wall elements (or actually
     45 * their identifier strings -- see below), thus forming a 2D polygonal path.
     46 *
     47 * Wall elements have the concept of an "inside" and "outside" direction. The "outside" direction is equivalent to the normal vector of the face formed
     48 * by the element in the polygonal path traced by its wall. By default, i.e. unrotated, the "outside" direction is taken to point towards the
     49 * positive X axis, i.e. to the right, and the "inside" direction similarly towards the negative X axis, i.e. to the left.
     50 *
     51 * At each step, consecutive wall elements are appended in the direction that is to the perpendicular left of the face normal (that is, the face normal
     52 * angle + 90 degrees anticlockwise). Hence, when placed without rotation (as is the default), the wall's course is straight up towards positive Y.
     53 * The course of the wall can be changed by means of the 'bending' property of individual wall elements; see parameter documentation for details.
     54 *
     55 * For the entity models to line up visually, they must all agree on a particular side to display towards this "outside" direction. Since models are free
     56 * to be modeled pointing any which way in their local object space, wall elements include a corrective angle to make the desired side of the model
     57 * correspond to the "outside" direction, i.e., to make that side point towards the right in their object space.
     58 *
     59 * @param type     Identifier for this wall element, e.g. "wallLong".
     60 * @param entity   Template name of the in-game entity for this element, e.g. "structures/cart_wall_long". Defaults to undefined (no entity placed).
     61 * @param angle    Corrective angle applied at placement time to ensure that the in-game entity aligns correctly with the "outside" direction.
     62 *                   Defaults to 0 (no correction applied).
     63 * @param width    Distance by which this wall element increases a wall's length, in world units. Defaults to 0 (no length increase).
     64 * @param indent   Lateral indentation of the wall element, in world units. May be positive for displacement along the "inside" vector, or negative
     65 *                   for displacement along the "outside" vector. Defaults to 0 (no lateral indentation).
     66 * @param bending  Change of course of a wall *after* having placed this element in its sequence, expressed as a change in the direction of the
     67 *                   face normal vector (aka. "outside" direction). May be positive for curving "inwards"/anticlockwise, or negative for curving
     68 *                   "outwards"/clockwise. Defaults to 0 (no change of course after this element).
     69 *                   NOTE: Not supported by all wall placement functions. See below for details.
     70 */
    5171function WallElement(type, entity, angle, width, indent, bending)
    5272{
    5373    this.type = type;
     
    7999    this.bending = (bending !== undefined) ? bending : 0*PI;
    80100}
    81101
    82 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    83 //  Fortress class definition
    84 //
    85 //  A "fortress" here is a closed wall build of multiple wall elements attached togather defined in Fortress.wall
    86 //  It's mainly the abstract shape defined in a Fortress instances wall because different styles can be used for it (see wallStyles)
    87 //
    88 //  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.
    90 //      Example: ["entrance", "wall", "cornerIn", "wall", "gate", "wall", "entrance", "wall", "cornerIn", "wall", "gate", "wall", "cornerIn", "wall"]
    91 //  centerToFirstElement  Optional. Object with propertys "x" and "y" representing a vector from the visual center to the first wall element. Default is undefined
    92 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     102/**
     103 * Fortress constructor.
     104 *
     105 * Defines a type of closed wall, where a wall is a sequence of WallElement identifiers as defined above. Not to be confused with in-game
     106 * fortress entities/models.
     107 *
     108 * Note that Fortresses are style-agnostic since they only reference WallElement identifiers (see below).
     109 * The corresponding WallElement instances for any particular style can be looked up via the global wallStyles map.
     110 *
     111 * @param {String} type  Identifier for this fortress, e.g. "tiny".
     112 * @param {Array}  wall  Optional; array of WallElement identifiers that make up the wall. Can be set/modified after construction. Defaults to the empty array.
     113 *                         Example value: ["entrance", "wall", "cornerIn", "wall"].
     114 * @param {Object} centerToFirstElement Optional; vector from the (visual) center of the fortress to the center of the first wall element, assuming a zero
     115 *                                        rotation. Defaults to undefined, in which case it will be taken to equal the center of mass when needed.
     116 */
    93117function Fortress(type, wall, centerToFirstElement)
    94118{
    95     this.type = type; // Only usefull to get the type of the actual fortress
     119    this.type = type;
    96120    this.wall = (wall !== undefined) ? wall : [];
    97121    this.centerToFirstElement = undefined;
    98122}
    99123
    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 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     124/**
     125 * wallStyles data structure for default wall styles
     126 *
     127 * A single wall style is an associative array that maps a set of WallElement identifier strings to their corresponding WallElements.
     128 * This global wallStyles data structure, then, holds a set of predefined wall styles, indexed by a style identifier (usually a civilization
     129 * name or another descriptive string, e.g. "athen", "rome_siege", "palisades", "fence", "road").
     130 */
    108131var wallStyles = {};
    109132
    110 // Generic civ dependent wall style definition. "rome_siege" needs some tweek...
     133// Generic civ-dependent wall style definitions. "rome_siege" needs some tweaking still ...
    111134var wallScaleByType = {"athen" : 1.5, "brit" : 1.5, "cart" : 1.8, "celt" : 1.5, "gaul" : 1.5, "hele" : 1.5, "iber" : 1.5, "mace" : 1.5, "pers" : 1.5, "rome" : 1.5, "spart" : 1.5, "rome_siege" : 1.5};
    112135for (var style in wallScaleByType)
    113136{
    114137    var civ = style;
    115138    if (style == "rome_siege")
    116139        civ = "rome";
     140   
    117141    wallStyles[style] = {};
     142   
    118143    // Default wall elements
    119144    wallStyles[style]["tower"] = new WallElement("tower", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]);
    120145    wallStyles[style]["endLeft"] = new WallElement("endLeft", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades...
     
    125150    wallStyles[style]["wall"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);
    126151    wallStyles[style]["wallMedium"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);
    127152    wallStyles[style]["wallLong"] = new WallElement("wallLong", "structures/" + style + "_wall_long", 0*PI, 6*wallScaleByType[style]);
     153   
    128154    // Gate and entrance wall elements
    129155    if (style == "cart")
    130156        var gateWidth = 3.5*wallScaleByType[style];
     
    132158        var gateWidth = 4*wallScaleByType[style];
    133159    else
    134160        var gateWidth = 6*wallScaleByType[style];
     161   
    135162    wallStyles[style]["gate"] = new WallElement("gate", "structures/" + style + "_wall_gate", 0*PI, gateWidth);
    136163    wallStyles[style]["entry"] = new WallElement("entry", undefined, 0*PI, gateWidth);
    137164    wallStyles[style]["entryTower"] = new WallElement("entryTower", "structures/" + civ + "_defense_tower", PI, gateWidth, -4*wallScaleByType[style]);
    138165    wallStyles[style]["entryFort"] = new WallElement("entryFort", "structures/" + civ + "_fortress", 0*PI, 8*wallScaleByType[style], 6*wallScaleByType[style]);
     166   
    139167    // Defensive wall elements with 0 width outside the wall
    140168    wallStyles[style]["outpost"] = new WallElement("outpost", "structures/" + civ + "_outpost", PI, 0, -4*wallScaleByType[style]);
    141169    wallStyles[style]["defenseTower"] = new WallElement("defenseTower", "structures/" + civ + "_defenseTower", PI, 0, -4*wallScaleByType[style]);
     170   
    142171    // Base buildings wall elements with 0 width inside the wall
    143172    wallStyles[style]["barracks"] = new WallElement("barracks", "structures/" + civ + "_barracks", PI, 0, 4.5*wallScaleByType[style]);
    144173    wallStyles[style]["civilCentre"] = new WallElement("civilCentre", "structures/" + civ + "_civil_centre", PI, 0, 4.5*wallScaleByType[style]);
     
    149178    wallStyles[style]["market"] = new WallElement("market", "structures/" + civ + "_market", PI, 0, 4.5*wallScaleByType[style]);
    150179    wallStyles[style]["mill"] = new WallElement("mill", "structures/" + civ + "_mill", PI, 0, 4.5*wallScaleByType[style]);
    151180    wallStyles[style]["temple"] = new WallElement("temple", "structures/" + civ + "_temple", PI, 0, 4.5*wallScaleByType[style]);
     181   
    152182    // Generic space/gap wall elements
    153183    wallStyles[style]["space1"] = new WallElement("space1", undefined, 0*PI, wallScaleByType[style]);
    154184    wallStyles[style]["space2"] = new WallElement("space2", undefined, 0*PI, 2*wallScaleByType[style]);
    155185    wallStyles[style]["space3"] = new WallElement("space3", undefined, 0*PI, 3*wallScaleByType[style]);
    156186    wallStyles[style]["space4"] = new WallElement("space4", undefined, 0*PI, 4*wallScaleByType[style]);
    157187}
    158 // Add wall fortresses for all generic styles
     188
     189// Add wall fortresses for all generic styles.
     190// Not to be confused with Fortress instances!
    159191wallStyles["athen"]["wallFort"] = new WallElement("wallFort", "structures/athen_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
    160192wallStyles["brit"]["wallFort"] = new WallElement("wallFort", "structures/brit_fortress", PI, 2.8);
    161193wallStyles["cart"]["wallFort"] = new WallElement("wallFort", "structures/cart_fortress", PI, 5.1, 1.6);
     
    167199wallStyles["pers"]["wallFort"] = new WallElement("wallFort", "structures/pers_fortress", PI, 5.6/*5.5*/, 1.9/*1.7*/);
    168200wallStyles["rome"]["wallFort"] = new WallElement("wallFort", "structures/rome_fortress", PI, 6.3, 2.1);
    169201wallStyles["spart"]["wallFort"] = new WallElement("wallFort", "structures/spart_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
     202
    170203// Adjust "rome_siege" style
    171204wallStyles["rome_siege"]["wallFort"] = new WallElement("wallFort", "structures/rome_army_camp", PI, 7.2, 2);
    172205wallStyles["rome_siege"]["entryFort"] = new WallElement("entryFort", "structures/rome_army_camp", PI, 12, 7);
     
    237270wallStyles["other"]["cornerOut"] = new WallElement("cornerOut", undefined, 0, 0, 0, -PI/2);
    238271
    239272
    240 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    241 //  fortressTypes data structure for some default fortress types
    242 //
    243 //  A fortress type is just an instance of the Fortress class with actually something in it
    244 //  fortressTypes holds all the fortressess within an associative array with a descriptive string as key (e.g. maching the map size)
    245 //  Eexamples: "tiny", "veryLarge"
    246 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     273/**
     274 * fortressTypes data structure for some default fortress types. Holds a set of predefined Fortresses, indexed by a descriptive string
     275 * (e.g. matching the map size: "tiny", "veryLarge", etc).
     276 */
     277
    247278var fortressTypes = {};
    248 // Setup some default fortress types
     279
    249280// Add fortress type "tiny"
    250281fortressTypes["tiny"] = new Fortress("tiny");
    251282var wallPart = ["entry", "wall", "cornerIn", "wall"];
    252283fortressTypes["tiny"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     284
    253285// Add fortress type "small"
    254286fortressTypes["small"] = new Fortress("small");
    255287var wallPart = ["entry", "endLeft", "wall", "cornerIn", "wall", "endRight"];
    256288fortressTypes["small"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     289
    257290// Add fortress type "medium"
    258291fortressTypes["medium"] = new Fortress("medium");
    259292var wallPart = ["entry", "endLeft", "wall", "outpost", "wall",
    260293    "cornerIn", "wall", "outpost", "wall", "endRight"];
    261294fortressTypes["medium"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     295
    262296// Add fortress type "normal"
    263297fortressTypes["normal"] = new Fortress("normal");
    264298var wallPart = ["entry", "endLeft", "wall", "tower", "wall",
    265299    "cornerIn", "wall", "tower", "wall", "endRight"];
    266300fortressTypes["normal"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     301
    267302// Add fortress type "large"
    268303fortressTypes["large"] = new Fortress("large");
    269304var wallPart = ["entry", "endLeft", "wall", "outpost", "wall", "cornerIn", "wall",
    270305    "cornerOut", "wall", "cornerIn", "wall", "outpost", "wall", "endRight"];
    271306fortressTypes["large"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     307
    272308// Add fortress type "veryLarge"
    273309fortressTypes["veryLarge"] = new Fortress("veryLarge");
    274310var wallPart = ["entry", "endLeft", "wall", "tower", "wall", "cornerIn", "wall",
    275311    "cornerOut", "wall", "cornerIn", "wall", "tower", "wall", "endRight"];
    276312fortressTypes["veryLarge"].wall = wallPart.concat(wallPart, wallPart, wallPart);
     313
    277314// Add fortress type "giant"
    278315fortressTypes["giant"] = new Fortress("giant");
    279316var wallPart = ["entry", "endLeft", "wall", "outpost", "wall", "cornerIn", "wall", "outpost", "wall",
    280317    "cornerOut", "wall", "outpost", "wall", "cornerIn", "wall", "outpost", "wall", "endRight"];
    281318fortressTypes["giant"].wall = wallPart.concat(wallPart, wallPart, wallPart);
    282319
    283 // Setup some better looking semi default fortresses for "palisades" style
     320// Setup some better looking semi default fortresses for the "palisades" style
    284321var fortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"];
    285322for (var i = 0; i < fortressTypeKeys.length; i++)
    286323{
     
    301338// TODO
    302339
    303340// Add some "fortress types" for roads (will only work with style "road")
    304 // ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft", "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"];
     341// ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft",
     342//  "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"];
    305343var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"];
    306344fortressTypes["road01"] = new Fortress("road01", wall);
     345
    307346var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"];
    308347fortressTypes["road02"] = new Fortress("road02", wall);
     348
    309349var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"];
    310350fortressTypes["road03"] = new Fortress("road03", wall);
     351
    311352var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short",
    312353    "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"];
    313354fortressTypes["road04"] = new Fortress("road04", wall);
     355
    314356var wall = ["start", "tLeft", "short", "xRight",
    315357    "curveLeft", "xRight", "tRight", "cornerLeft", "tRight",
    316358    "curveLeft", "short", "tRight", "cornerLeft", "xRight",
     
    322364// Define some helper functions
    323365///////////////////////////////
    324366
    325 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    326 //  getWallAlignment
    327 //
    328 //  Returns a list of objects containing all information to place all the wall elements entities with placeObject (but the player ID)
    329 //  Placing the first wall element at startX/startY placed with an angle given by orientation
    330 //  An alignement can be used to get the "center" of a "wall" (more likely used for fortresses) with getCenterToFirstElement
    331 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     367/**
     368 * Returns a list of objects specifying the placement parameters for the entities required to build the given wall at the specified
     369 * starting location and orientation. Each object contains data suitable for use with placeObject (see library.js).
     370 *
     371 * The returned value is called an "alignment", and is of the form:
     372 *     [{x: ..., y: ..., entity: ..., angle: ...},
     373 *       ...]
     374 *
     375 * @param startX       X location (in world units) of the center of the first wall element to be placed.
     376 * @param startY       Y location (in world units) of the center of the first wall element to be placed.
     377 * @param wall         Array of WallElement identifier strings. Should exist as keys in wallStyles[style] (see the style parameter).
     378 * @param style        Style identifier string to use for the wall elements. See the global wallStyles array.
     379 * @param orientation  Initial rotation of the "outside" direction (or face normal vector) to begin placement with, relative CCW to the
     380 *                       positive X-axis.
     381 */
    332382function getWallAlignment(startX, startY, wall, style, orientation)
    333383{
    334384    orientation = (orientation || 0);
    335385    var alignment = [];
    336386    var wallX = startX;
    337387    var wallY = startY;
     388   
    338389    for (var i = 0; i < wall.length; i++)
    339390    {
    340391        var element = wallStyles[style][wall[i]];
    341         if (element === undefined && i == 0)
     392        if (element === undefined/* && i == 0*/)
    342393            warn("No valid wall element: " + wall[i]);
     394       
    343395        // Indentation
    344396        var placeX = wallX - element.indent * cos(orientation);
    345397        var placeY = wallY - element.indent * sin(orientation);
     398       
    346399        // Add wall elements entity placement arguments to the alignment
    347400        alignment.push({"x": placeX, "y": placeY, "entity": element.entity, "angle":orientation + element.angle});
     401       
    348402        // Preset vars for the next wall element
    349403        if (i+1 < wall.length)
    350404        {
     
    352406            var nextElement = wallStyles[style][wall[i+1]];
    353407            if (nextElement === undefined)
    354408                warn("No valid wall element: " + wall[i+1]);
     409           
    355410            var distance = (element.width + nextElement.width)/2;
     411           
    356412            // Corrections for elements with indent AND bending
    357413            var indent = element.indent;
    358414            var bending = element.bending;
     
    372428    return alignment;
    373429}
    374430
    375 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    376 //  getCenterToFirstElement
    377 //
    378 //  Center calculation works like getting the center of mass assuming all wall elements have the same "weight"
    379 //
    380 //  It returns the vector from the center to the first wall element
    381 //  Used to get centerToFirstElement of fortresses by default
    382 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     431/**
     432 * Returns a vector from the center of mass of the given wall to the center of its first entity, at zero rotation of the wall,
     433 * and assuming all wall entities have the same weight. Used to compute the centers of Fortresses if none is otherwise given
     434 * (see the Fortress class).
     435 */
    383436function getCenterToFirstElement(alignment)
    384437{
    385438    var centerToFirstElement = {"x": 0, "y": 0};
     
    417470//
    418471//  Places a wall with wall elements attached to another like determined by WallElement properties.
    419472//
    420 //  startX, startY  Where the first wall element should be placed
    421 //  wall            Array of wall element type strings. Example: ["endLeft", "wallLong", "tower", "wallLong", "endRight"]
    422 //  style           Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    423 //  playerId        Optional. Number of the player the wall will be placed for. Default is 0 (gaia)
    424 //  orientation     Optional. Angle the first wall element is placed. Default is 0
    425 //                  0 means "outside" or "front" of the wall is right (positive X) like placeObject
    426 //                  It will then be build towards top/positive Y (if no bending wall elements like corners are used)
    427 //                  Raising orientation means the wall is rotated counter-clockwise like placeObject
     473//  startX, startY  Location of the center of the first wall element, in world units.
     474//  wall            Array of WallElement identifier strings. Example: ["endLeft", "wallLong", "tower", "wallLong", "endRight"]
     475//  style           Optional. Wall style string. Default is the civ of the given player, or "palisades" for gaia or if no player is given.
     476//                    See the global wallStyles array.
     477//  playerId        Optional. Player ID of the owner of the wall. Default is 0 (gaia).
     478//  orientation     Optional. Initial rotation of the "outside" direction (or face normal vector) to begin placement with, relative CCW to the
     479//                    positive X-axis (as in placeObject).
    428480/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    429481function placeWall(startX, startY, wall, style, playerId, orientation)
    430482{
     
    435487    else
    436488        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
    437489    orientation = (orientation || 0);
     490   
    438491    // Get wall alignment
    439492    var AM = getWallAlignment(startX, startY, wall, style, orientation);
     493   
    440494    // Place the wall
    441495    for (var iWall = 0; iWall < wall.length; iWall++)
    442496    {
     
    449503/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    450504//  placeCustomFortress
    451505//
    452 //  Place a fortress (mainly a closed wall build like placeWall) centered at centerX/centerY
    453 //  The fortress wall should always start with the main entrance (like "entry" or "gate") to get the orientation right (like placeObject)
    454 //
    455 //  fortress       An instance of Fortress with a wall defined
    456 //  style          Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    457 //  playerId       Optional. Number of the player the wall will be placed for. Default is 0 (gaia)
    458 //  orientation    Optional. Angle the first wall element (should be a gate or entrance) is placed. Default is 0
     506//  Places a fortress centered at centerX/centerY.
     507//  The fortress wall should always start with a main entrance (e.g. the WallElements "entry" or "gate") to get the orientation right
     508//  (like placeObject).
     509// 
     510//  centerX, centerY  Location of the center of mass of the fortress, in world units.
     511//  fortress          An instance of Fortress, with a wall defined.
     512//  style             Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia or if no player is given.
     513//                      See the global wallStyles array.
     514//  playerId          Optional. Player ID of the owner of the wall. Default is 0 (gaia).
     515//  orientation       Optional. Initial rotation of the "outside" direction (or face normal vector) to begin placement with, relative CCW to the
     516//                      positive X-axis (as in placeObject).
    459517/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    460518function placeCustomFortress(centerX, centerY, fortress, style, playerId, orientation)
    461519{
     
    467525    else
    468526        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
    469527    orientation = (orientation || 0);
     528   
    470529    // Calculate center if fortress.centerToFirstElement is undefined (default)
    471530    var centerToFirstElement = fortress.centerToFirstElement;
    472531    if (centerToFirstElement === undefined)
    473532        centerToFirstElement = getCenterToFirstElement(getWallAlignment(0, 0, fortress.wall, style));
     533   
    474534    // Placing the fortress wall
    475535    var startX = centerX + centerToFirstElement.x * cos(orientation) - centerToFirstElement.y * sin(orientation);
    476536    var startY = centerY + centerToFirstElement.y * cos(orientation) + centerToFirstElement.x * sin(orientation);
    477     placeWall(startX, startY, fortress.wall, style, playerId, orientation)
     537    placeWall(startX, startY, fortress.wall, style, playerId, orientation);
    478538}
    479539
    480540///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    481541//  placeFortress
    482542//
    483 //  Like placeCustomFortress just it takes type (a fortress type string, has to be in fortressTypes) instead of an instance of Fortress
     543//  Like placeCustomFortress, but takes a fortress type identifier instead of an instance of Fortress (which must be defined in fortressTypes).
    484544///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    485545function placeFortress(centerX, centerY, type, style, playerId, orientation)
    486546{
     
    492552    else
    493553        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
    494554    orientation = (orientation || 0);
     555   
    495556    // Call placeCustomFortress with the given arguments
    496557    placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation);
    497558}
     
    520581    else
    521582        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
    522583    endWithFirst = typeof endWithFirst == "undefined" ? true : endWithFirst;
     584   
    523585    // Check arguments
    524586    for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    525587    {
     
    527589        if (bending != 0)
    528590            warn("Bending is not supported by placeLinearWall but a bending wall element is used: " + wallPart[elementIndex] + " -> wallStyles[style][wallPart[elementIndex]].entity");
    529591    }
     592   
    530593    // Setup number of wall parts
    531594    var totalLength = getDistance(startX, startY, targetX, targetY);
    532595    var wallPartLength = 0;
     
    537600        numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength);
    538601    else
    539602        numParts = ceil(totalLength / wallPartLength);
     603   
    540604    // Setup scale factor
    541605    var scaleFactor = 1;
    542606    if (endWithFirst == true)
    543607        scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);
    544608    else
    545609        scaleFactor = totalLength / (numParts * wallPartLength);
     610   
    546611    // Setup angle
    547612    var wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed...
    548613    var placeAngle = wallAngle - PI/2;
     614   
    549615    // Place wall entities
    550616    var x = startX;
    551617    var y = startY;
     
    554620        for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    555621        {
    556622            var wallEle = wallStyles[style][wallPart[elementIndex]];
     623           
    557624            // Width correction
    558625            x += scaleFactor * wallEle.width/2 * cos(wallAngle);
    559626            y += scaleFactor * wallEle.width/2 * sin(wallAngle);
     627           
    560628            // Indent correction
    561629            var placeX = x - wallEle.indent * sin(wallAngle);
    562630            var placeY = y + wallEle.indent * cos(wallAngle);
     631           
    563632            // Placement
    564633            var entity = wallEle.entity;
    565634            if (entity !== undefined)
     
    587656//  The orientation then determines where this open part faces (0 means right like unrotated building's droppoints)
    588657//
    589658//  centerX/Y     Coordinates of the circle's center
    590 //  radius        How wide the circle should be (aproximate, especially if maxBendOff != 0)
     659//  radius        How wide the circle should be (approximately, especially if maxBendOff != 0)
    591660//  wallPart      Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"]
    592661//  style         Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia
    593662//  playerId      Optional. Integer number of the player. Default is 0 (gaia)
     
    597666//  maxBendOff    Optional. How irregular the circle should be. 0 means regular circle, PI/2 means very irregular. Default is 0 (regular circle)
    598667//
    599668//  NOTE: Don't use wall elements with bending like corners!
    600 //  TODO: Perhaps add eccentricity and maxBendOff functionality (untill now an unused argument)
     669//  TODO: Perhaps add eccentricity and maxBendOff functionality (until now an unused argument)
    601670//  TODO: Perhaps add functionality for spirals
    602671/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    603672function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle, endWithFirst, maxBendOff)
     
    611680        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
    612681    orientation = (orientation || 0);
    613682    maxAngle = (maxAngle || 2*PI);
     683   
    614684    if (endWithFirst === undefined)
    615685    {
    616686        if (maxAngle >= 2*PI - 0.001) // Can this be done better?
     
    619689            endWithFirst = true;
    620690    }
    621691    maxBendOff = (maxBendOff || 0);
     692   
    622693    // Check arguments
    623694    if (maxBendOff > PI/2 || maxBendOff < 0)
    624695        warn("placeCircularWall maxBendOff sould satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff);
     
    628699        if (bending != 0)
    629700            warn("Bending is not supported by placeCircularWall but a bending wall element is used: " + wallPart[elementIndex]);
    630701    }
     702   
    631703    // Setup number of wall parts
    632704    var totalLength = maxAngle * radius;
    633705    var wallPartLength = 0;
     
    642714    {
    643715        numParts = ceil(totalLength / wallPartLength);
    644716    }
     717   
    645718    // Setup scale factor
    646719    var scaleFactor = 1;
    647720    if (endWithFirst == true)
    648721        scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);
    649722    else
    650723        scaleFactor = totalLength / (numParts * wallPartLength);
     724   
    651725    // Place wall entities
    652726    var actualAngle = orientation + (2*PI - maxAngle) / 2;
    653727    var x = centerX + radius*cos(actualAngle);
     
    657731        for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
    658732        {
    659733            var wallEle = wallStyles[style][wallPart[elementIndex]];
     734           
    660735            // Width correction
    661736            var addAngle = scaleFactor * wallEle.width / radius;
    662737            var targetX = centerX + radius * cos(actualAngle + addAngle);
     
    664739            var placeX = x + (targetX - x)/2;
    665740            var placeY = y + (targetY - y)/2;
    666741            var placeAngle = actualAngle + addAngle/2;
     742           
    667743            // Indent correction
    668744            placeX -= wallEle.indent * cos(placeAngle);
    669745            placeY -= wallEle.indent * sin(placeAngle);
     746           
    670747            // Placement
    671748            var entity = wallEle.entity;
    672749            if (entity !== undefined)
    673750                placeObject(placeX, placeY, entity, playerId, placeAngle + wallEle.angle);
     751           
    674752            // Prepare for the next wall element
    675753            actualAngle += addAngle;
    676754            x = centerX + radius*cos(actualAngle);
     
    723801    orientation = (orientation || 0);
    724802    numCorners = (numCorners || 8);
    725803    skipFirstWall = (skipFirstWall || true);
     804   
    726805    // Setup angles
    727806    var angleAdd = 2*PI/numCorners;
    728807    var angleStart = orientation - angleAdd/2;
     808   
    729809    // Setup corners
    730810    var corners = [];
    731811    for (var i = 0; i < numCorners; i++)
    732812        corners.push([centerX + radius*cos(angleStart + i*angleAdd), centerY + radius*sin(angleStart + i*angleAdd)]);
     813   
    733814    // Place Corners and walls
    734815    for (var i = 0; i < numCorners; i++)
    735816    {
     
    778859        style = (style || "palisades");
    779860    else
    780861        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
     862   
    781863    // Generating a generic wall part assortment with each wall part including 1 gate enlengthend by walls and towers
    782864    // NOTE: It might be a good idea to write an own function for that...
    783865    var defaultWallPartsAssortment = [["wallShort"], ["wall"], ["wallLong"], ["gate", "tower", "wallShort"]];
     
    800882            defaultWallPartsAssortment.push(wallPart);
    801883        }
    802884    }
     885   
    803886    // Setup optional arguments to the default
    804887    wallPartsAssortment = (wallPartsAssortment || defaultWallPartsAssortment);
    805888    cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well...
     
    809892    numCorners = (numCorners || randInt(5, 7));
    810893    irregularity = (irregularity || 0.5);
    811894    skipFirstWall = (skipFirstWall || false);
     895   
    812896    // Setup angles
    813897    var angleToCover = 2*PI;
    814898    var angleAddList = [];
     
    818902        angleAddList.push(angleToCover/(numCorners-i) * (1 + randFloat(-irregularity, irregularity)));
    819903        angleToCover -= angleAddList[angleAddList.length - 1];
    820904    }
     905   
    821906    // Setup corners
    822907    var corners = [];
    823908    var angleActual = orientation - angleAddList[0]/2;
     
    827912        if (i < numCorners - 1)
    828913            angleActual += angleAddList[i+1];
    829914    }
     915   
    830916    // Setup best wall parts for the different walls (a bit confusing naming...)
    831917    var wallPartLengths = [];
    832918    var maxWallPartLength = 0;
     
    840926    var wallPartList = []; // This is the list of the wall parts to use for the walls between the corners, not to confuse with wallPartsAssortment!
    841927    for (var i = 0; i < numCorners; i++)
    842928    {
    843         var bestWallPart = []; // This is a simpel wall part not a wallPartsAssortment!
     929        var bestWallPart = []; // This is a simple wall part not a wallPartsAssortment!
    844930        var bestWallLength = 99999999;
    845         // NOTE: This is not exsactly like the length the wall will be in the end. Has to be tweeked...
     931        // NOTE: This is not exactly like the length the wall will be in the end. Has to be tweaked...
    846932        var wallLength = getDistance(corners[i][0], corners[i][1], corners[(i+1)%numCorners][0], corners[(i+1)%numCorners][1]);
    847933        var numWallParts = ceil(wallLength/maxWallPartLength);
    848934        for (var partIndex = 0; partIndex < wallPartsAssortment.length; partIndex++)
     
    856942        }
    857943        wallPartList.push(bestWallPart);
    858944    }
     945   
    859946    // Place Corners and walls
    860947    for (var i = 0; i < numCorners; i++)
    861948    {
     
    897984        style = (style || "palisades");
    898985    else
    899986        style = (style || g_MapSettings.PlayerData[playerId-1].Civ);
     987   
    900988    irregularity = (irregularity || 1/2);
    901989    gateOccurence = (gateOccurence || 3);
    902990    maxTrys = (maxTrys || 100);
     991   
    903992    // Setup some vars
    904993    var startAngle = randFloat(0, 2*PI);
    905994    var actualOffX = radius*cos(startAngle);
    906995    var actualOffY = radius*sin(startAngle);
    907996    var actualAngle = startAngle;
    908997    var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width;
     998   
    909999    // Searching for a well fitting point derivation
    9101000    var tries = 0;
    9111001    var bestPointDerivation = undefined;
     
    9221012            var tmpAngle = getAngle(actualOffX, actualOffY,
    9231013                (radius + indent)*cos(actualAngle + (pointDistance / radius)),
    9241014                (radius + indent)*sin(actualAngle + (pointDistance / radius)));
     1015           
    9251016            actualOffX += pointDistance*cos(tmpAngle);
    9261017            actualOffY += pointDistance*sin(tmpAngle);
    9271018            actualAngle = getAngle(0, 0, actualOffX, actualOffY);
    9281019            pointDerivation.push([actualOffX, actualOffY]);
    9291020            distanceToTarget = getDistance(actualOffX, actualOffY, pointDerivation[0][0], pointDerivation[0][1]);
     1021           
    9301022            var numPoints = pointDerivation.length;
    9311023            if (numPoints > 3 && distanceToTarget < pointDistance) // Could be done better...
    9321024            {
     
    9511043        var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1];
    9521044        var angle = getAngle(startX, startY, targetX, targetY);
    9531045        var wallElement = "wallLong";
     1046       
    9541047        if ((pointIndex + 1) % gateOccurence == 0)
    9551048            wallElement = "entry"; // Has to be changed to "gate" if gates work...
     1049       
    9561050        var entity = wallStyles[style][wallElement].entity;
    9571051        if (entity)
    9581052        {
     
    9601054                startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY
    9611055                entity, playerId, angle - PI/2 + wallStyles[style][wallElement].angle);
    9621056        }
     1057       
    9631058        // Place tower
    9641059        var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0];
    9651060        var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1];