Ticket #1449: 1449_rms_wall_overlap6_comments.patch
File 1449_rms_wall_overlap6_comments.patch, 39.3 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/maps/random/rmgen/library.js
331 331 } 332 332 } 333 333 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 */ 334 342 function placeObject(x, z, type, player, angle) 335 343 { 336 344 g_Map.addObject(new Entity(type, player, x, z, angle)); -
binaries/data/mods/public/maps/random/rmgen/wall_builder.js
33 33 // ?Think of something to enable splitting walls into two walls so more complex walls can be build and roads can have branches/crossroads? 34 34 // ?Readjust placement angle for wall elements with bending when used in linear/circular walls by their bending? 35 35 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 */ 36 40 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 */ 51 71 function WallElement(type, entity, angle, width, indent, bending) 52 72 { 53 73 this.type = type; … … 79 99 this.bending = (bending !== undefined) ? bending : 0*PI; 80 100 } 81 101 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 */ 93 117 function Fortress(type, wall, centerToFirstElement) 94 118 { 95 this.type = type; // Only usefull to get the type of the actual fortress119 this.type = type; 96 120 this.wall = (wall !== undefined) ? wall : []; 97 121 this.centerToFirstElement = undefined; 98 122 } 99 123 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 */ 108 131 var wallStyles = {}; 109 132 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 ... 111 134 var 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}; 112 135 for (var style in wallScaleByType) 113 136 { 114 137 var civ = style; 115 138 if (style == "rome_siege") 116 139 civ = "rome"; 140 117 141 wallStyles[style] = {}; 142 118 143 // Default wall elements 119 144 wallStyles[style]["tower"] = new WallElement("tower", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); 120 145 wallStyles[style]["endLeft"] = new WallElement("endLeft", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades... … … 125 150 wallStyles[style]["wall"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]); 126 151 wallStyles[style]["wallMedium"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]); 127 152 wallStyles[style]["wallLong"] = new WallElement("wallLong", "structures/" + style + "_wall_long", 0*PI, 6*wallScaleByType[style]); 153 128 154 // Gate and entrance wall elements 129 155 if (style == "cart") 130 156 var gateWidth = 3.5*wallScaleByType[style]; … … 132 158 var gateWidth = 4*wallScaleByType[style]; 133 159 else 134 160 var gateWidth = 6*wallScaleByType[style]; 161 135 162 wallStyles[style]["gate"] = new WallElement("gate", "structures/" + style + "_wall_gate", 0*PI, gateWidth); 136 163 wallStyles[style]["entry"] = new WallElement("entry", undefined, 0*PI, gateWidth); 137 164 wallStyles[style]["entryTower"] = new WallElement("entryTower", "structures/" + civ + "_defense_tower", PI, gateWidth, -4*wallScaleByType[style]); 138 165 wallStyles[style]["entryFort"] = new WallElement("entryFort", "structures/" + civ + "_fortress", 0*PI, 8*wallScaleByType[style], 6*wallScaleByType[style]); 166 139 167 // Defensive wall elements with 0 width outside the wall 140 168 wallStyles[style]["outpost"] = new WallElement("outpost", "structures/" + civ + "_outpost", PI, 0, -4*wallScaleByType[style]); 141 169 wallStyles[style]["defenseTower"] = new WallElement("defenseTower", "structures/" + civ + "_defenseTower", PI, 0, -4*wallScaleByType[style]); 170 142 171 // Base buildings wall elements with 0 width inside the wall 143 172 wallStyles[style]["barracks"] = new WallElement("barracks", "structures/" + civ + "_barracks", PI, 0, 4.5*wallScaleByType[style]); 144 173 wallStyles[style]["civilCentre"] = new WallElement("civilCentre", "structures/" + civ + "_civil_centre", PI, 0, 4.5*wallScaleByType[style]); … … 149 178 wallStyles[style]["market"] = new WallElement("market", "structures/" + civ + "_market", PI, 0, 4.5*wallScaleByType[style]); 150 179 wallStyles[style]["mill"] = new WallElement("mill", "structures/" + civ + "_mill", PI, 0, 4.5*wallScaleByType[style]); 151 180 wallStyles[style]["temple"] = new WallElement("temple", "structures/" + civ + "_temple", PI, 0, 4.5*wallScaleByType[style]); 181 152 182 // Generic space/gap wall elements 153 183 wallStyles[style]["space1"] = new WallElement("space1", undefined, 0*PI, wallScaleByType[style]); 154 184 wallStyles[style]["space2"] = new WallElement("space2", undefined, 0*PI, 2*wallScaleByType[style]); 155 185 wallStyles[style]["space3"] = new WallElement("space3", undefined, 0*PI, 3*wallScaleByType[style]); 156 186 wallStyles[style]["space4"] = new WallElement("space4", undefined, 0*PI, 4*wallScaleByType[style]); 157 187 } 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! 159 191 wallStyles["athen"]["wallFort"] = new WallElement("wallFort", "structures/athen_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */); 160 192 wallStyles["brit"]["wallFort"] = new WallElement("wallFort", "structures/brit_fortress", PI, 2.8); 161 193 wallStyles["cart"]["wallFort"] = new WallElement("wallFort", "structures/cart_fortress", PI, 5.1, 1.6); … … 167 199 wallStyles["pers"]["wallFort"] = new WallElement("wallFort", "structures/pers_fortress", PI, 5.6/*5.5*/, 1.9/*1.7*/); 168 200 wallStyles["rome"]["wallFort"] = new WallElement("wallFort", "structures/rome_fortress", PI, 6.3, 2.1); 169 201 wallStyles["spart"]["wallFort"] = new WallElement("wallFort", "structures/spart_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */); 202 170 203 // Adjust "rome_siege" style 171 204 wallStyles["rome_siege"]["wallFort"] = new WallElement("wallFort", "structures/rome_army_camp", PI, 7.2, 2); 172 205 wallStyles["rome_siege"]["entryFort"] = new WallElement("entryFort", "structures/rome_army_camp", PI, 12, 7); … … 237 270 wallStyles["other"]["cornerOut"] = new WallElement("cornerOut", undefined, 0, 0, 0, -PI/2); 238 271 239 272 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 247 278 var fortressTypes = {}; 248 // Setup some default fortress types 279 249 280 // Add fortress type "tiny" 250 281 fortressTypes["tiny"] = new Fortress("tiny"); 251 282 var wallPart = ["entry", "wall", "cornerIn", "wall"]; 252 283 fortressTypes["tiny"].wall = wallPart.concat(wallPart, wallPart, wallPart); 284 253 285 // Add fortress type "small" 254 286 fortressTypes["small"] = new Fortress("small"); 255 287 var wallPart = ["entry", "endLeft", "wall", "cornerIn", "wall", "endRight"]; 256 288 fortressTypes["small"].wall = wallPart.concat(wallPart, wallPart, wallPart); 289 257 290 // Add fortress type "medium" 258 291 fortressTypes["medium"] = new Fortress("medium"); 259 292 var wallPart = ["entry", "endLeft", "wall", "outpost", "wall", 260 293 "cornerIn", "wall", "outpost", "wall", "endRight"]; 261 294 fortressTypes["medium"].wall = wallPart.concat(wallPart, wallPart, wallPart); 295 262 296 // Add fortress type "normal" 263 297 fortressTypes["normal"] = new Fortress("normal"); 264 298 var wallPart = ["entry", "endLeft", "wall", "tower", "wall", 265 299 "cornerIn", "wall", "tower", "wall", "endRight"]; 266 300 fortressTypes["normal"].wall = wallPart.concat(wallPart, wallPart, wallPart); 301 267 302 // Add fortress type "large" 268 303 fortressTypes["large"] = new Fortress("large"); 269 304 var wallPart = ["entry", "endLeft", "wall", "outpost", "wall", "cornerIn", "wall", 270 305 "cornerOut", "wall", "cornerIn", "wall", "outpost", "wall", "endRight"]; 271 306 fortressTypes["large"].wall = wallPart.concat(wallPart, wallPart, wallPart); 307 272 308 // Add fortress type "veryLarge" 273 309 fortressTypes["veryLarge"] = new Fortress("veryLarge"); 274 310 var wallPart = ["entry", "endLeft", "wall", "tower", "wall", "cornerIn", "wall", 275 311 "cornerOut", "wall", "cornerIn", "wall", "tower", "wall", "endRight"]; 276 312 fortressTypes["veryLarge"].wall = wallPart.concat(wallPart, wallPart, wallPart); 313 277 314 // Add fortress type "giant" 278 315 fortressTypes["giant"] = new Fortress("giant"); 279 316 var wallPart = ["entry", "endLeft", "wall", "outpost", "wall", "cornerIn", "wall", "outpost", "wall", 280 317 "cornerOut", "wall", "outpost", "wall", "cornerIn", "wall", "outpost", "wall", "endRight"]; 281 318 fortressTypes["giant"].wall = wallPart.concat(wallPart, wallPart, wallPart); 282 319 283 // Setup some better looking semi default fortresses for "palisades" style320 // Setup some better looking semi default fortresses for the "palisades" style 284 321 var fortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"]; 285 322 for (var i = 0; i < fortressTypeKeys.length; i++) 286 323 { … … 301 338 // TODO 302 339 303 340 // 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"]; 305 343 var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"]; 306 344 fortressTypes["road01"] = new Fortress("road01", wall); 345 307 346 var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"]; 308 347 fortressTypes["road02"] = new Fortress("road02", wall); 348 309 349 var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"]; 310 350 fortressTypes["road03"] = new Fortress("road03", wall); 351 311 352 var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short", 312 353 "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"]; 313 354 fortressTypes["road04"] = new Fortress("road04", wall); 355 314 356 var wall = ["start", "tLeft", "short", "xRight", 315 357 "curveLeft", "xRight", "tRight", "cornerLeft", "tRight", 316 358 "curveLeft", "short", "tRight", "cornerLeft", "xRight", … … 322 364 // Define some helper functions 323 365 /////////////////////////////// 324 366 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 */ 332 382 function getWallAlignment(startX, startY, wall, style, orientation) 333 383 { 334 384 orientation = (orientation || 0); 335 385 var alignment = []; 336 386 var wallX = startX; 337 387 var wallY = startY; 388 338 389 for (var i = 0; i < wall.length; i++) 339 390 { 340 391 var element = wallStyles[style][wall[i]]; 341 if (element === undefined && i == 0)392 if (element === undefined/* && i == 0*/) 342 393 warn("No valid wall element: " + wall[i]); 394 343 395 // Indentation 344 396 var placeX = wallX - element.indent * cos(orientation); 345 397 var placeY = wallY - element.indent * sin(orientation); 398 346 399 // Add wall elements entity placement arguments to the alignment 347 400 alignment.push({"x": placeX, "y": placeY, "entity": element.entity, "angle":orientation + element.angle}); 401 348 402 // Preset vars for the next wall element 349 403 if (i+1 < wall.length) 350 404 { … … 352 406 var nextElement = wallStyles[style][wall[i+1]]; 353 407 if (nextElement === undefined) 354 408 warn("No valid wall element: " + wall[i+1]); 409 355 410 var distance = (element.width + nextElement.width)/2; 411 356 412 // Corrections for elements with indent AND bending 357 413 var indent = element.indent; 358 414 var bending = element.bending; … … 372 428 return alignment; 373 429 } 374 430 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 */ 383 436 function getCenterToFirstElement(alignment) 384 437 { 385 438 var centerToFirstElement = {"x": 0, "y": 0}; … … 417 470 // 418 471 // Places a wall with wall elements attached to another like determined by WallElement properties. 419 472 // 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). 428 480 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 429 481 function placeWall(startX, startY, wall, style, playerId, orientation) 430 482 { … … 435 487 else 436 488 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 437 489 orientation = (orientation || 0); 490 438 491 // Get wall alignment 439 492 var AM = getWallAlignment(startX, startY, wall, style, orientation); 493 440 494 // Place the wall 441 495 for (var iWall = 0; iWall < wall.length; iWall++) 442 496 { … … 449 503 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 450 504 // placeCustomFortress 451 505 // 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). 459 517 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 460 518 function placeCustomFortress(centerX, centerY, fortress, style, playerId, orientation) 461 519 { … … 467 525 else 468 526 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 469 527 orientation = (orientation || 0); 528 470 529 // Calculate center if fortress.centerToFirstElement is undefined (default) 471 530 var centerToFirstElement = fortress.centerToFirstElement; 472 531 if (centerToFirstElement === undefined) 473 532 centerToFirstElement = getCenterToFirstElement(getWallAlignment(0, 0, fortress.wall, style)); 533 474 534 // Placing the fortress wall 475 535 var startX = centerX + centerToFirstElement.x * cos(orientation) - centerToFirstElement.y * sin(orientation); 476 536 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); 478 538 } 479 539 480 540 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 481 541 // placeFortress 482 542 // 483 // Like placeCustomFortress just it takes type (a fortress type string, has to be in fortressTypes) instead of an instance of Fortress543 // Like placeCustomFortress, but takes a fortress type identifier instead of an instance of Fortress (which must be defined in fortressTypes). 484 544 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 485 545 function placeFortress(centerX, centerY, type, style, playerId, orientation) 486 546 { … … 492 552 else 493 553 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 494 554 orientation = (orientation || 0); 555 495 556 // Call placeCustomFortress with the given arguments 496 557 placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation); 497 558 } … … 520 581 else 521 582 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 522 583 endWithFirst = typeof endWithFirst == "undefined" ? true : endWithFirst; 584 523 585 // Check arguments 524 586 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 525 587 { … … 527 589 if (bending != 0) 528 590 warn("Bending is not supported by placeLinearWall but a bending wall element is used: " + wallPart[elementIndex] + " -> wallStyles[style][wallPart[elementIndex]].entity"); 529 591 } 592 530 593 // Setup number of wall parts 531 594 var totalLength = getDistance(startX, startY, targetX, targetY); 532 595 var wallPartLength = 0; … … 537 600 numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength); 538 601 else 539 602 numParts = ceil(totalLength / wallPartLength); 603 540 604 // Setup scale factor 541 605 var scaleFactor = 1; 542 606 if (endWithFirst == true) 543 607 scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width); 544 608 else 545 609 scaleFactor = totalLength / (numParts * wallPartLength); 610 546 611 // Setup angle 547 612 var wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed... 548 613 var placeAngle = wallAngle - PI/2; 614 549 615 // Place wall entities 550 616 var x = startX; 551 617 var y = startY; … … 554 620 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 555 621 { 556 622 var wallEle = wallStyles[style][wallPart[elementIndex]]; 623 557 624 // Width correction 558 625 x += scaleFactor * wallEle.width/2 * cos(wallAngle); 559 626 y += scaleFactor * wallEle.width/2 * sin(wallAngle); 627 560 628 // Indent correction 561 629 var placeX = x - wallEle.indent * sin(wallAngle); 562 630 var placeY = y + wallEle.indent * cos(wallAngle); 631 563 632 // Placement 564 633 var entity = wallEle.entity; 565 634 if (entity !== undefined) … … 587 656 // The orientation then determines where this open part faces (0 means right like unrotated building's droppoints) 588 657 // 589 658 // centerX/Y Coordinates of the circle's center 590 // radius How wide the circle should be (ap roximate, especially if maxBendOff != 0)659 // radius How wide the circle should be (approximately, especially if maxBendOff != 0) 591 660 // wallPart Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"] 592 661 // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia 593 662 // playerId Optional. Integer number of the player. Default is 0 (gaia) … … 597 666 // maxBendOff Optional. How irregular the circle should be. 0 means regular circle, PI/2 means very irregular. Default is 0 (regular circle) 598 667 // 599 668 // NOTE: Don't use wall elements with bending like corners! 600 // TODO: Perhaps add eccentricity and maxBendOff functionality (until lnow an unused argument)669 // TODO: Perhaps add eccentricity and maxBendOff functionality (until now an unused argument) 601 670 // TODO: Perhaps add functionality for spirals 602 671 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 603 672 function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle, endWithFirst, maxBendOff) … … 611 680 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 612 681 orientation = (orientation || 0); 613 682 maxAngle = (maxAngle || 2*PI); 683 614 684 if (endWithFirst === undefined) 615 685 { 616 686 if (maxAngle >= 2*PI - 0.001) // Can this be done better? … … 619 689 endWithFirst = true; 620 690 } 621 691 maxBendOff = (maxBendOff || 0); 692 622 693 // Check arguments 623 694 if (maxBendOff > PI/2 || maxBendOff < 0) 624 695 warn("placeCircularWall maxBendOff sould satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff); … … 628 699 if (bending != 0) 629 700 warn("Bending is not supported by placeCircularWall but a bending wall element is used: " + wallPart[elementIndex]); 630 701 } 702 631 703 // Setup number of wall parts 632 704 var totalLength = maxAngle * radius; 633 705 var wallPartLength = 0; … … 642 714 { 643 715 numParts = ceil(totalLength / wallPartLength); 644 716 } 717 645 718 // Setup scale factor 646 719 var scaleFactor = 1; 647 720 if (endWithFirst == true) 648 721 scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width); 649 722 else 650 723 scaleFactor = totalLength / (numParts * wallPartLength); 724 651 725 // Place wall entities 652 726 var actualAngle = orientation + (2*PI - maxAngle) / 2; 653 727 var x = centerX + radius*cos(actualAngle); … … 657 731 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 658 732 { 659 733 var wallEle = wallStyles[style][wallPart[elementIndex]]; 734 660 735 // Width correction 661 736 var addAngle = scaleFactor * wallEle.width / radius; 662 737 var targetX = centerX + radius * cos(actualAngle + addAngle); … … 664 739 var placeX = x + (targetX - x)/2; 665 740 var placeY = y + (targetY - y)/2; 666 741 var placeAngle = actualAngle + addAngle/2; 742 667 743 // Indent correction 668 744 placeX -= wallEle.indent * cos(placeAngle); 669 745 placeY -= wallEle.indent * sin(placeAngle); 746 670 747 // Placement 671 748 var entity = wallEle.entity; 672 749 if (entity !== undefined) 673 750 placeObject(placeX, placeY, entity, playerId, placeAngle + wallEle.angle); 751 674 752 // Prepare for the next wall element 675 753 actualAngle += addAngle; 676 754 x = centerX + radius*cos(actualAngle); … … 723 801 orientation = (orientation || 0); 724 802 numCorners = (numCorners || 8); 725 803 skipFirstWall = (skipFirstWall || true); 804 726 805 // Setup angles 727 806 var angleAdd = 2*PI/numCorners; 728 807 var angleStart = orientation - angleAdd/2; 808 729 809 // Setup corners 730 810 var corners = []; 731 811 for (var i = 0; i < numCorners; i++) 732 812 corners.push([centerX + radius*cos(angleStart + i*angleAdd), centerY + radius*sin(angleStart + i*angleAdd)]); 813 733 814 // Place Corners and walls 734 815 for (var i = 0; i < numCorners; i++) 735 816 { … … 778 859 style = (style || "palisades"); 779 860 else 780 861 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 862 781 863 // Generating a generic wall part assortment with each wall part including 1 gate enlengthend by walls and towers 782 864 // NOTE: It might be a good idea to write an own function for that... 783 865 var defaultWallPartsAssortment = [["wallShort"], ["wall"], ["wallLong"], ["gate", "tower", "wallShort"]]; … … 800 882 defaultWallPartsAssortment.push(wallPart); 801 883 } 802 884 } 885 803 886 // Setup optional arguments to the default 804 887 wallPartsAssortment = (wallPartsAssortment || defaultWallPartsAssortment); 805 888 cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well... … … 809 892 numCorners = (numCorners || randInt(5, 7)); 810 893 irregularity = (irregularity || 0.5); 811 894 skipFirstWall = (skipFirstWall || false); 895 812 896 // Setup angles 813 897 var angleToCover = 2*PI; 814 898 var angleAddList = []; … … 818 902 angleAddList.push(angleToCover/(numCorners-i) * (1 + randFloat(-irregularity, irregularity))); 819 903 angleToCover -= angleAddList[angleAddList.length - 1]; 820 904 } 905 821 906 // Setup corners 822 907 var corners = []; 823 908 var angleActual = orientation - angleAddList[0]/2; … … 827 912 if (i < numCorners - 1) 828 913 angleActual += angleAddList[i+1]; 829 914 } 915 830 916 // Setup best wall parts for the different walls (a bit confusing naming...) 831 917 var wallPartLengths = []; 832 918 var maxWallPartLength = 0; … … 840 926 var wallPartList = []; // This is the list of the wall parts to use for the walls between the corners, not to confuse with wallPartsAssortment! 841 927 for (var i = 0; i < numCorners; i++) 842 928 { 843 var bestWallPart = []; // This is a simp elwall part not a wallPartsAssortment!929 var bestWallPart = []; // This is a simple wall part not a wallPartsAssortment! 844 930 var bestWallLength = 99999999; 845 // NOTE: This is not ex sactly 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... 846 932 var wallLength = getDistance(corners[i][0], corners[i][1], corners[(i+1)%numCorners][0], corners[(i+1)%numCorners][1]); 847 933 var numWallParts = ceil(wallLength/maxWallPartLength); 848 934 for (var partIndex = 0; partIndex < wallPartsAssortment.length; partIndex++) … … 856 942 } 857 943 wallPartList.push(bestWallPart); 858 944 } 945 859 946 // Place Corners and walls 860 947 for (var i = 0; i < numCorners; i++) 861 948 { … … 897 984 style = (style || "palisades"); 898 985 else 899 986 style = (style || g_MapSettings.PlayerData[playerId-1].Civ); 987 900 988 irregularity = (irregularity || 1/2); 901 989 gateOccurence = (gateOccurence || 3); 902 990 maxTrys = (maxTrys || 100); 991 903 992 // Setup some vars 904 993 var startAngle = randFloat(0, 2*PI); 905 994 var actualOffX = radius*cos(startAngle); 906 995 var actualOffY = radius*sin(startAngle); 907 996 var actualAngle = startAngle; 908 997 var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width; 998 909 999 // Searching for a well fitting point derivation 910 1000 var tries = 0; 911 1001 var bestPointDerivation = undefined; … … 922 1012 var tmpAngle = getAngle(actualOffX, actualOffY, 923 1013 (radius + indent)*cos(actualAngle + (pointDistance / radius)), 924 1014 (radius + indent)*sin(actualAngle + (pointDistance / radius))); 1015 925 1016 actualOffX += pointDistance*cos(tmpAngle); 926 1017 actualOffY += pointDistance*sin(tmpAngle); 927 1018 actualAngle = getAngle(0, 0, actualOffX, actualOffY); 928 1019 pointDerivation.push([actualOffX, actualOffY]); 929 1020 distanceToTarget = getDistance(actualOffX, actualOffY, pointDerivation[0][0], pointDerivation[0][1]); 1021 930 1022 var numPoints = pointDerivation.length; 931 1023 if (numPoints > 3 && distanceToTarget < pointDistance) // Could be done better... 932 1024 { … … 951 1043 var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1]; 952 1044 var angle = getAngle(startX, startY, targetX, targetY); 953 1045 var wallElement = "wallLong"; 1046 954 1047 if ((pointIndex + 1) % gateOccurence == 0) 955 1048 wallElement = "entry"; // Has to be changed to "gate" if gates work... 1049 956 1050 var entity = wallStyles[style][wallElement].entity; 957 1051 if (entity) 958 1052 { … … 960 1054 startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY 961 1055 entity, playerId, angle - PI/2 + wallStyles[style][wallElement].angle); 962 1056 } 1057 963 1058 // Place tower 964 1059 var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0]; 965 1060 var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1];