6 | | // Rename wall elements to fit he entity names so that entity = 'structures/' + 'civ + '_' + wallElement.type in the common case |
7 | | // Add roman army camp to style palisades and add upgraded default palisade fortress types matching civ default fortresses |
8 | | // Add further wall elements cornerHalfIn, cornerHalfOut and adjust default fortress types to better fit in the octagonal territory of a civil center |
9 | | // Add civil center, corral, farmstead, field, market, mill, temple |
| 6 | // Check if all wall placement methods work with wall elements with entity === undefined |
| 7 | // Rename wall elements to fit he entity names so that entity = 'structures/' + 'civ + '_' + wallElement.type in the common case (as far as possible) |
| 8 | // Perhaps add roman army camp to style palisades and add upgraded default palisade fortress types matching civ default fortresses |
| 9 | // perhaps add further wall elements cornerHalfIn, cornerHalfOut and adjust default fortress types to better fit in the octagonal territory of a civil center |
| 10 | // Perhaps swap angle and width in WallElement class(?) definition |
20 | | /////////////////////////////// |
21 | | // WallElement class definition |
22 | | /////////////////////////////// |
23 | | |
24 | | // argument type: Descriptive string, example: 'wall'. NOTE: Not really needed. Mainly for custom wall elements and to get the wall element type in code. |
25 | | // argument entity: Optional. Template string to be placed, example: 'structures/cart_wall'. Default is undefined (No entity placed) |
26 | | // argument angle: Optional. Placement angle so that 'outside' is 'right' (towards positive X like a unit placed with angle 0). Default is 0 (0*PI) |
27 | | // argument width: Optional. The width it lengthens the wall, width because it's the needed space in a right angle to 'outside'. Default is 0 |
28 | | // argument indent: Optional. The indentation means its drawn inside (positive values) or pushed outwards (negative values). Default is 0 |
29 | | // NOTE: Bending is only used for fortresses and custom walls. Linear/circular walls walls use no/generic bending |
30 | | // argument bending: Optional. How the direction of the wall is changed after this element, positive is bending 'in' (counter clockwise like entity placement) |
| 20 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 21 | // WallElement class definition |
| 22 | // |
| 23 | // type: Descriptive string, example: 'wall'. NOTE: Not really needed. Mainly for custom wall elements and to get the wall element type in code. |
| 24 | // entity: Optional. Template string to be placed, example: 'structures/cart_wall'. Default is undefined (No entity placed) |
| 25 | // angle: Optional. Placement angle so that 'outside' is 'right' (towards positive X like a unit placed with angle 0). Default is 0 (0*PI) |
| 26 | // width: Optional. The width it lengthens the wall, width because it's the needed space in a right angle to 'outside'. Default is 0 |
| 27 | // indent: Optional. The indentation means its drawn inside (positive values) or pushed outwards (negative values). Default is 0 |
| 28 | // bending: Optional. How the direction of the wall is changed after this element, positive is bending 'in' (counter clockwise like entity placement) |
| 29 | // |
| 30 | // NOTE: Bending is only used for fortresses and custom walls. Linear/circular walls walls use no/generic bending |
| 31 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
67 | | |
68 | | //////////////////////////// |
69 | | // Fortress class definition |
70 | | //////////////////////////// |
71 | | |
72 | | // A list would do for symetric fortresses but if 'getCenter' don't do sufficient the center can be set manually |
73 | | // argument type: Descriptive string, example: 'tiny'. Not really needed (WallTool.wallTypes['type string'] is used). Mainly for custom wall elements. |
74 | | // argument wall: Optional. Array of wall element strings. Can be set afterwards. Default is an epty array. |
75 | | // Example: ['entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'cornerIn', 'wall'] |
76 | | // argument center: Optional. Array of 2 floats determinig the vector from the center to the 1st wall element. Can be set afterwards. Default is [0, 0]. (REALLY???) |
77 | | // NOTE: The center will be recalculated when WallTool.setFortress is called. To avoid this set WallTool.calculateCenter to false. |
| 68 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 69 | // Fortress class definition |
| 70 | // |
| 71 | // A list would do for symetric fortresses but if 'getCenter' don't do sufficient the center can be set manually |
| 72 | // |
| 73 | // type: Descriptive string, example: 'tiny'. Not really needed (WallTool.wallTypes['type string'] is used). Mainly for custom wall elements. |
| 74 | // wall: Optional. Array of wall element strings. Can be set afterwards. Default is an epty array. |
| 75 | // Example: ['entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'cornerIn', 'wall'] |
| 76 | // center: Optional. Array of 2 floats determinig the vector from the center to the 1st wall element. Can be set afterwards. Default is [0, 0]. (REALLY???) |
| 77 | // |
| 78 | // NOTE: The center will be recalculated when WallTool.setFortress is called. To avoid this set WallTool.calculateCenter to false. |
| 79 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
86 | | /////////////////////////////////////////////// |
87 | | // Setup data structure for default wall styles |
88 | | /////////////////////////////////////////////// |
89 | | |
90 | | // A wall style is an associative array with all wall elements of that style in it associated with the wall element type string. |
91 | | // wallStyles holds all the wall styles within an associative array while a wall style is associated with the civ string or another descriptive strings like 'palisades', 'fence', 'cart', 'celt'... |
| 88 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 89 | // wallStyles data structure for default wall styles |
| 90 | // |
| 91 | // A wall style is an associative array with all wall elements of that style in it associated with the wall element type string |
| 92 | // wallStyles holds all the wall styles within an associative array with the civ string or another descriptive strings as key |
| 93 | // Examples: "athen", "rome_siege", "palisades", "fence", "road" |
| 94 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
95 | | var scaleByCiv = {'athen' : 1.5, 'cart' : 1.8, 'celt' : 1.5, 'hele' : 1.5, 'iber' : 1.5, 'mace' : 1.5, 'pers' : 1.5, 'rome' : 1.5, 'spart' : 1.5, 'rome_siege' : 1.5}; |
96 | | for (var style in scaleByCiv) |
| 98 | 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}; |
| 99 | for (var style in wallScaleByType) |
103 | | wallStyles[style]['tower'] = new WallElement('tower', 'structures/' + style + '_wall_tower', PI, scaleByCiv[style]); |
104 | | wallStyles[style]['endLeft'] = new WallElement('endLeft', 'structures/' + style + '_wall_tower', PI, scaleByCiv[style]); // Same as tower. To be compatible with palisades... |
105 | | wallStyles[style]['endRight'] = new WallElement('endRight', 'structures/' + style + '_wall_tower', PI, scaleByCiv[style]); // Same as tower. To be compatible with palisades... |
106 | | wallStyles[style]['cornerIn'] = new WallElement('cornerIn', 'structures/' + style + '_wall_tower', 5*PI/4, 0, 0.35*scaleByCiv[style], PI/2); // 2^0.5 / 4 ~= 0.35 ~= 1/3 |
107 | | wallStyles[style]['cornerOut'] = new WallElement('cornerOut', 'structures/' + style + '_wall_tower', 3*PI/4, 0.71*scaleByCiv[style], 0, -PI/2); // // 2^0.5 / 2 ~= 0.71 ~= 2/3 |
108 | | wallStyles[style]['wallShort'] = new WallElement('wallShort', 'structures/' + style + '_wall_short', 0*PI, 2*scaleByCiv[style]); |
109 | | wallStyles[style]['wall'] = new WallElement('wall', 'structures/' + style + '_wall_medium', 0*PI, 4*scaleByCiv[style]); |
110 | | wallStyles[style]['wallLong'] = new WallElement('wallLong', 'structures/' + style + '_wall_long', 0*PI, 6*scaleByCiv[style]); |
| 106 | wallStyles[style]['tower'] = new WallElement('tower', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); |
| 107 | wallStyles[style]['endLeft'] = new WallElement('endLeft', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades... |
| 108 | wallStyles[style]['endRight'] = new WallElement('endRight', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades... |
| 109 | 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 |
| 110 | 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 |
| 111 | wallStyles[style]['wallShort'] = new WallElement('wallShort', 'structures/' + style + '_wall_short', 0*PI, 2*wallScaleByType[style]); |
| 112 | wallStyles[style]['wall'] = new WallElement('wall', 'structures/' + style + '_wall_medium', 0*PI, 4*wallScaleByType[style]); |
| 113 | wallStyles[style]['wallMedium'] = new WallElement('wall', 'structures/' + style + '_wall_medium', 0*PI, 4*wallScaleByType[style]); |
| 114 | wallStyles[style]['wallLong'] = new WallElement('wallLong', 'structures/' + style + '_wall_long', 0*PI, 6*wallScaleByType[style]); |
122 | | if (civ == 'iber') // Adjust iberians to have no upkeep at entries with a tower for convinience ATM, may be changed |
123 | | wallStyles[style]['entryTower'] = new WallElement('entryTower', 'structures/' + civ + '_wall_tower', PI, gateWidth, -4*scaleByCiv[style]); |
124 | | else |
125 | | wallStyles[style]['entryTower'] = new WallElement('entryTower', 'structures/' + civ + '_defense_tower', PI, gateWidth, -4*scaleByCiv[style]); |
126 | | wallStyles[style]['entryFort'] = new WallElement('entryFort', 'structures/' + civ + '_fortress', 0*PI, 8*scaleByCiv[style], 6*scaleByCiv[style]); |
| 126 | wallStyles[style]['entryTower'] = new WallElement('entryTower', 'structures/' + civ + '_defense_tower', PI, gateWidth, -4*wallScaleByType[style]); |
| 127 | wallStyles[style]['entryFort'] = new WallElement('entryFort', 'structures/' + civ + '_fortress', 0*PI, 8*wallScaleByType[style], 6*wallScaleByType[style]); |
131 | | wallStyles[style]['barracks'] = new WallElement('barracks', 'structures/' + civ + '_barracks', PI, 0, 4.5*scaleByCiv[style]); |
132 | | wallStyles[style]['civilCentre'] = new WallElement('civilCentre', 'structures/' + civ + '_civil_centre', PI, 0, 4.5*scaleByCiv[style]); |
133 | | wallStyles[style]['farmstead'] = new WallElement('farmstead', 'structures/' + civ + '_farmstead', PI, 0, 4.5*scaleByCiv[style]); |
134 | | wallStyles[style]['field'] = new WallElement('field', 'structures/' + civ + '_field', PI, 0, 4.5*scaleByCiv[style]); |
135 | | wallStyles[style]['fortress'] = new WallElement('fortress', 'structures/' + civ + '_fortress', PI, 0, 4.5*scaleByCiv[style]); |
136 | | wallStyles[style]['house'] = new WallElement('house', 'structures/' + civ + '_house', PI, 0, 4.5*scaleByCiv[style]); |
137 | | wallStyles[style]['market'] = new WallElement('market', 'structures/' + civ + '_market', PI, 0, 4.5*scaleByCiv[style]); |
138 | | wallStyles[style]['mill'] = new WallElement('mill', 'structures/' + civ + '_mill', PI, 0, 4.5*scaleByCiv[style]); |
139 | | wallStyles[style]['temple'] = new WallElement('temple', 'structures/' + civ + '_temple', PI, 0, 4.5*scaleByCiv[style]); |
| 132 | wallStyles[style]['barracks'] = new WallElement('barracks', 'structures/' + civ + '_barracks', PI, 0, 4.5*wallScaleByType[style]); |
| 133 | wallStyles[style]['civilCentre'] = new WallElement('civilCentre', 'structures/' + civ + '_civil_centre', PI, 0, 4.5*wallScaleByType[style]); |
| 134 | wallStyles[style]['farmstead'] = new WallElement('farmstead', 'structures/' + civ + '_farmstead', PI, 0, 4.5*wallScaleByType[style]); |
| 135 | wallStyles[style]['field'] = new WallElement('field', 'structures/' + civ + '_field', PI, 0, 4.5*wallScaleByType[style]); |
| 136 | wallStyles[style]['fortress'] = new WallElement('fortress', 'structures/' + civ + '_fortress', PI, 0, 4.5*wallScaleByType[style]); |
| 137 | wallStyles[style]['house'] = new WallElement('house', 'structures/' + civ + '_house', PI, 0, 4.5*wallScaleByType[style]); |
| 138 | wallStyles[style]['market'] = new WallElement('market', 'structures/' + civ + '_market', PI, 0, 4.5*wallScaleByType[style]); |
| 139 | wallStyles[style]['mill'] = new WallElement('mill', 'structures/' + civ + '_mill', PI, 0, 4.5*wallScaleByType[style]); |
| 140 | wallStyles[style]['temple'] = new WallElement('temple', 'structures/' + civ + '_temple', PI, 0, 4.5*wallScaleByType[style]); |
141 | | wallStyles[style]['space1'] = new WallElement('space1', undefined, 0*PI, scaleByCiv[style]); |
142 | | wallStyles[style]['space2'] = new WallElement('space2', undefined, 0*PI, 2*scaleByCiv[style]); |
143 | | wallStyles[style]['space3'] = new WallElement('space3', undefined, 0*PI, 3*scaleByCiv[style]); |
144 | | wallStyles[style]['space4'] = new WallElement('space4', undefined, 0*PI, 4*scaleByCiv[style]); |
| 142 | wallStyles[style]['space1'] = new WallElement('space1', undefined, 0*PI, wallScaleByType[style]); |
| 143 | wallStyles[style]['space2'] = new WallElement('space2', undefined, 0*PI, 2*wallScaleByType[style]); |
| 144 | wallStyles[style]['space3'] = new WallElement('space3', undefined, 0*PI, 3*wallScaleByType[style]); |
| 145 | wallStyles[style]['space4'] = new WallElement('space4', undefined, 0*PI, 4*wallScaleByType[style]); |
| 190 | // NOTE: This is not a wall style in the common sense. Use with care! |
| 191 | wallStyles['road'] = {}; |
| 192 | wallStyles['road']['short'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_short.xml", PI/2, 4.5); |
| 193 | wallStyles['road']['long'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_long.xml", PI/2, 9.5); |
| 194 | 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 |
| 195 | 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 |
| 196 | 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 |
| 197 | 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 |
| 198 | wallStyles['road']['start'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_end.xml", PI/2, 2); |
| 199 | wallStyles['road']['end'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_end.xml", -PI/2, 2); |
| 200 | wallStyles['road']['xStraight'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5); |
| 201 | wallStyles['road']['xLeft'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, PI/2); |
| 202 | wallStyles['road']['xRight'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, -PI/2); |
| 203 | wallStyles['road']['tLeft'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_T.xml", PI, 4.5, 1.25); |
| 204 | wallStyles['road']['tRight'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_T.xml", 0*PI, 4.5, -1.25); |
209 | | /////////////////////////////////////////////////////// |
210 | | // Setup data structure for some default fortress types |
211 | | /////////////////////////////////////////////////////// |
212 | | |
213 | | // A fortress type is just an instance of the fortress class with actually something in it. |
214 | | // fortressTypes holds all the fortressess within an associative array while a fortress is associated with a descriptive string maching the map sizes, example: 'tiny', 'giant' |
| 231 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 232 | // fortressTypes data structure for some default fortress types |
| 233 | // |
| 234 | // A fortress type is just an instance of the fortress class with actually something in it |
| 235 | // fortressTypes holds all the fortressess within an associative array with a descriptive string as key (e.g. maching the map size) |
| 236 | // Eexamples: "tiny', "veryLarge" |
| 237 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
251 | | // Add (some) iberian civ bonus fortress (The civ can still be set, just an uncommon default fortress) |
252 | | var wall = ['gate', 'tower', 'wall', 'cornerIn', 'wallLong', 'tower', |
253 | | 'gate', 'tower', 'wallLong', 'cornerIn', 'wall', 'tower', |
254 | | 'gate', 'wall', 'cornerIn', 'wall', 'cornerOut', 'wall', 'cornerIn', 'wallLong', 'tower', |
255 | | 'gate', 'tower', 'wallLong', 'cornerIn', 'wall', 'tower', 'wall', 'cornerIn', 'wall']; |
256 | | fortressTypes['iberCivBonus'] = new Fortress('iberCivBonus', wall); |
257 | | var wall = ['gate', 'tower', 'wall', 'cornerIn', 'wall', 'cornerOut', 'wall', 'cornerIn', 'wallLong', 'tower', |
258 | | 'gate', 'tower', 'wallLong', 'cornerIn', 'wall', 'tower', 'wall', 'cornerIn', 'wall', 'cornerOut', |
259 | | 'gate', 'tower', 'wall', 'cornerIn', 'wallLong', 'tower', |
260 | | 'gate', 'tower', 'wallLong', 'cornerIn', 'wall', 'tower']; |
261 | | fortressTypes['iberCivBonus2'] = new Fortress('iberCivBonus2', wall); |
262 | | var wall = ['gate', 'tower', 'wall', 'cornerOut', 'wallShort', 'cornerIn', 'wall', 'cornerIn', 'wallLong', 'cornerIn', 'wallShort', 'cornerOut', 'wall', 'tower', |
263 | | 'gate', 'tower', 'wallLong', 'cornerIn', 'wallLong', 'cornerIn', 'wallShort', 'cornerOut', |
264 | | 'gate', 'tower', 'wall', 'cornerIn', 'wall', 'cornerOut', 'wallShort', 'cornerIn', 'wall', 'tower', |
265 | | 'gate', 'tower', 'wallShort', 'cornerIn', 'wall', 'tower', 'wallShort', 'tower']; |
266 | | fortressTypes['iberCivBonus3'] = new Fortress('iberCivBonus3', wall); |
267 | | |
268 | | |
| 291 | // Add some "fortress types" for roads (will only work with style "road") |
| 292 | // ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft", "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"]; |
| 293 | var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"]; |
| 294 | fortressTypes['road01'] = new Fortress('road01', wall); |
| 295 | var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"]; |
| 296 | fortressTypes['road02'] = new Fortress('road02', wall); |
| 297 | var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"]; |
| 298 | fortressTypes['road03'] = new Fortress('road03', wall); |
| 299 | var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short", |
| 300 | "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"]; |
| 301 | fortressTypes['road04'] = new Fortress('road04', wall); |
| 302 | var wall = ["start", "tLeft", "short", "xRight", |
| 303 | "curveLeft", "xRight", "tRight", "cornerLeft", "tRight", |
| 304 | "curveLeft", "short", "tRight", "cornerLeft", "xRight", |
| 305 | "cornerLeft", "xRight", "short", "tRight", "curveLeft", "end"]; |
| 306 | fortressTypes['road05'] = new Fortress('road05', wall); |
291 | | // Get alignment of a wall |
292 | | // Returns a list of lists of most arguments needed to place the different wall elements for a given wall |
293 | | // Placing the first wall element at startX/startY placed with angle given by orientation |
294 | | // An alignement can be used to get the center of a 'wall' (more likely used for closed walls like fortresses) with the getWallCenter function |
| 309 | /////////////////////////////// |
| 310 | // Define some helper functions |
| 311 | /////////////////////////////// |
| 312 | |
| 313 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 314 | // getWallAlignment |
| 315 | // |
| 316 | // Returns a list of lists of most arguments needed to place the different wall elements for a given wall |
| 317 | // Placing the first wall element at startX/startY placed with angle given by orientation |
| 318 | // An alignement can be used to get the center of a 'wall' (more likely used for fortresses) with the getWallCenter function |
| 319 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
369 | | ///////////////////////////////////////////////////////////////////////////////// |
370 | | // Place simple wall starting with the first wall element placed at startX/startY |
371 | | ///////////////////////////////////////////////////////////////////////////////// |
372 | | // orientation: 0 means 'outside' or 'front' of the wall is right (positive X) like placeObject |
373 | | // It will then be build towards top (positive Y) if no bending wall elements like corners are used |
374 | | // Raising orientation means the wall is rotated counter-clockwise like placeObject |
| 402 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 403 | // placeWall |
| 404 | // |
| 405 | // Places a wall with wall elements attached to another like determined by WallElement properties. |
| 406 | // |
| 407 | // startX, startY Where the first wall element should be placed |
| 408 | // wall Array of wall element type strings. Example: ["endLeft", "wallLong", "tower", "wallLong", "endRight"] |
| 409 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 410 | // playerId Optional. Number of the player the wall will be placed for. Default is 0 (gaia) |
| 411 | // orientation Optional. Angle the first wall element is placed. Default is 0 |
| 412 | // 0 means 'outside' or 'front' of the wall is right (positive X) like placeObject |
| 413 | // It will then be build towards top/positive Y (if no bending wall elements like corners are used) |
| 414 | // Raising orientation means the wall is rotated counter-clockwise like placeObject |
| 415 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
385 | | ////////////////////////////////////////////////////////////////////////////////////////////////// |
386 | | // Place a fortress (mainly a closed wall build like placeWall) with the center at centerX/centerY |
387 | | ////////////////////////////////////////////////////////////////////////////////////////////////// |
388 | | // Should always start with the main entrance (like 'entry' or 'gate') to get the orientation right (like placeObject) |
| 435 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 436 | // placeCustomFortress |
| 437 | // |
| 438 | // Place a fortress (mainly a closed wall build like placeWall) centered at centerX/centerY (if scipGetCenter is not set otherwise) |
| 439 | // The fortress wall should always start with the main entrance (like 'entry' or 'gate') to get the orientation right (like placeObject) |
| 440 | // |
| 441 | // fortress An instance of Fortress with a wall defined |
| 442 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 443 | // playerId Optional. Number of the player the wall will be placed for. Default is 0 (gaia) |
| 444 | // orientation Optional. Angle the first wall element (should be a gate or entrance) is placed. Default is 0 |
| 445 | // scipGetCenter Optional. If true it places the first wall element at centerX/centerY. Default is false |
| 446 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
411 | | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
412 | | // Place a linear wall of repeatant wall elements given in the argument wallPart from startX/startY to targetX/targetY |
413 | | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
414 | | // startX: x coordinate of the beginning of the wall |
415 | | // startY: y coordinate of the beginning of the wall |
416 | | // targetX: x coordinate of the ending of the wall |
417 | | // targetY: y coordinate of the ending of the wall |
418 | | // NOTE: Start and target coordinates are exact (besides the scale offset) meaning the wall will begin/end at the given coordinates (not the first/last entity is placed there) |
419 | | // wallPart: Optional. An array of wall element type strings (see WallElement.type). Default is ['wall'] |
420 | | // NOTE: Don't use wall elements with bending like corners! |
421 | | // style: Optional. An wall style string (like defined in the 'wallStyles' dictionary). Default is 'palisades' |
422 | | // playerId: Optional. The walls owners player ID (like in the function 'placeObject' so 0 is gaia, 1 is the first player), Default is 0 (gaia) |
423 | | // endWithFirst: Optional. A boolean value. If true the 1st wall element in the wallPart array will finalize the wall. Default is true |
| 495 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 496 | // placeLinearWall |
| 497 | // |
| 498 | // Places a straight wall from a given coordinate to an other repeatant using the wall parts. |
| 499 | // |
| 500 | // startX/startY Coordinate of the approximate beginning of the wall (Not the place of the first wall element) |
| 501 | // targetX/targetY Coordinate of the approximate ending of the wall (Not the place of the last wall element) |
| 502 | // wallPart Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"] |
| 503 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 504 | // playerId Optional. Integer number of the player. Default is 0 (gaia) |
| 505 | // endWithFirst Optional. A boolean value. If true the 1st wall element in the wallPart array will finalize the wall. Default is true |
| 506 | // |
| 507 | // TODO: Maybe add angle offset for more generic looking? |
| 508 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
486 | | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
487 | | // Place a circular wall of repeatant wall elements given in the argument wallPart arround centerX/centerY with the given radius |
488 | | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
489 | | // The wall is not necessarily closed depending on the optional argument maxAngle (better name?) |
490 | | // NOTE: Don't use wall elements with bending like corners! |
491 | | // Todo: add eccentricity |
| 573 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 574 | // placeCircularWall |
| 575 | // |
| 576 | // Place a circular wall of repeatant wall elements given in the argument wallPart arround centerX/centerY with the given radius |
| 577 | // |
| 578 | // The wall is not necessarily closed depending on the optional argument maxAngle (better name?) |
| 579 | // NOTE: Don't use wall elements with bending like corners! |
| 580 | // TODO: Perhaps add eccentricity and maxBendOff functionality (untill now an unused argument) |
| 581 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
724 | | // Just a test function, USE WITH CARE! |
725 | | // radius: A float seting the aproximate radius of the fortress |
726 | | // maxBendOff: Optional, The maximum random bending offset of the wall elements NOTE: If maxBendOff > PI/2 the wall might never close!!! |
727 | | // wallPart: Optional, An array of wall element string, example: ["tower", "wall"] NOTE: Don't use wall elements with bending!!! |
728 | | function placeGenericFortress(centerX, centerY, radius, playerId, wallPart, style, maxBendOff) |
| 831 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 832 | // placeGenericFortress |
| 833 | // |
| 834 | // Places a generic fortress with towers at the edges connected with long walls and gates (entries untill gates work) |
| 835 | // |
| 836 | // This is the default Iberian civ bonus starting wall |
| 837 | // |
| 838 | // radius The approximate radius of the wall to be placed |
| 839 | // playerId Optional. Integer number of the player. Default is 0 (gaia) |
| 840 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 841 | // irregularity Optional. Float between 0 (circle) and 1 (very spiky), default is 1/2 |
| 842 | // gateOccurence Optional. Integer number, every n-th walls will be a gate instead. Default is 3 |
| 843 | // maxTrys Optional. How often the function tries to find a better fitting shape at max. Default is 100 |
| 844 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 845 | function placeGenericFortress(centerX, centerY, radius, playerId, style, irregularity, gateOccurence, maxTrys) |
730 | | if (wallPart == undefined) |
731 | | wallPart = ['tower', 'wall', 'tower', 'entry', 'tower', 'wall']; |
732 | | if (maxBendOff > PI/2 || maxBendOff < 0) |
733 | | warn("setGenericFortress maxBendOff sould satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff); |
734 | | if (maxBendOff === undefined) |
735 | | maxBendOff = 0; |
736 | | var wallLength = 0; |
737 | | for (var eleIndex = 0; eleIndex < wallPart.length; eleIndex++) |
| 847 | // Setup optional arguments |
| 848 | radius = (radius || 20); |
| 849 | playerId = (playerId || 0); |
| 850 | if (playerId == 0) |
| 851 | style = (style || "palisades"); |
| 852 | else |
| 853 | style = (style || g_MapSettings.PlayerData[playerId-1].Civ); |
| 854 | irregularity = (irregularity || 1/2); |
| 855 | gateOccurence = (gateOccurence || 3); |
| 856 | maxTrys = (maxTrys || 100); |
| 857 | // Setup some vars |
| 858 | var startAngle = randFloat(0, 2*PI); |
| 859 | var actualOffX = radius*cos(startAngle); |
| 860 | var actualOffY = radius*sin(startAngle); |
| 861 | var actualAngle = startAngle; |
| 862 | var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width; |
| 863 | // Searching for a well fitting point derivation |
| 864 | var tries = 0; |
| 865 | var bestPointDerivation = undefined; |
| 866 | var minOverlap = 1000; |
| 867 | var overlap = undefined; |
| 868 | while (tries < maxTrys && minOverlap > wallStyles[style]["tower"].width / 10) |
739 | | wallLength += wallStyles[style][wallPart[eleIndex]].width |
| 870 | var pointDerivation = []; |
| 871 | var distanceToTarget = 1000; |
| 872 | var targetReached = false; |
| 873 | while (!targetReached) |
| 874 | { |
| 875 | var indent = randFloat(-irregularity*pointDistance, irregularity*pointDistance); |
| 876 | var tmpAngle = getAngle(actualOffX, actualOffY, |
| 877 | (radius + indent)*cos(actualAngle + (pointDistance / radius)), |
| 878 | (radius + indent)*sin(actualAngle + (pointDistance / radius))); |
| 879 | actualOffX += pointDistance*cos(tmpAngle); |
| 880 | actualOffY += pointDistance*sin(tmpAngle); |
| 881 | actualAngle = getAngle(0, 0, actualOffX, actualOffY); |
| 882 | pointDerivation.push([actualOffX, actualOffY]); |
| 883 | distanceToTarget = getDistance(actualOffX, actualOffY, pointDerivation[0][0], pointDerivation[0][1]); |
| 884 | if ( pointDerivation.length > 3 && distanceToTarget < pointDistance) // Could be done better... |
| 885 | { |
| 886 | targetReached = true; |
| 887 | overlap = pointDistance - getDistance(pointDerivation[pointDerivation.length - 1][0], pointDerivation[pointDerivation.length - 1][1], pointDerivation[0][0], pointDerivation[0][1]); |
| 888 | if (overlap < minOverlap) |
| 889 | { |
| 890 | minOverlap = overlap; |
| 891 | bestPointDerivation = pointDerivation; |
| 892 | } |
| 893 | } |
| 894 | } |
| 895 | tries++; |
747 | | eleWidth = wallStyles[style][wallPart[eleIndex]].width; |
748 | | if (eleWidth < minEleWidth) |
749 | | minEleWidth = eleWidth; |
| 901 | var startX = centerX + bestPointDerivation[pointIndex][0]; |
| 902 | var startY = centerY + bestPointDerivation[pointIndex][1]; |
| 903 | var targetX = centerX + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][0]; |
| 904 | var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1]; |
| 905 | var angle = getAngle(startX, startY, targetX, targetY); |
| 906 | var wallElement = "wallLong"; |
| 907 | if ((pointIndex + 1) % gateOccurence == 0) |
| 908 | wallElement = "entry"; // Has to be changed to "gate" if gates work... |
| 909 | if (wallStyles[style][wallElement].entity) |
| 910 | { |
| 911 | placeObject(startX + (getDistance(startX, startY, targetX, targetY)/2)*cos(angle), // placeX |
| 912 | startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY |
| 913 | wallStyles[style][wallElement].entity, playerId, angle - PI/2 + wallStyles[style][wallElement].angle); |
| 914 | } |
| 915 | // Place tower |
| 916 | var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0]; |
| 917 | var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1]; |
| 918 | var angle = getAngle(startX, startY, targetX, targetY); |
| 919 | placeObject(centerX + bestPointDerivation[pointIndex][0], centerY + bestPointDerivation[pointIndex][1], wallStyles[style]["tower"].entity, playerId, angle - PI/2 + wallStyles[style]["tower"].angle); |
751 | | var widthSafty = minEleWidth/4; // Can be done better... |
752 | | |
| 921 | } |
| 922 | |
| 923 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 924 | // placeOrganicFortress |
| 925 | // |
| 926 | // Place an generic 'organic' looking wall of repeatant wall elements given by wallPart roughly arround centerX/centerY with roughly the given radius |
| 927 | // NOTE: This is the old/obsolete Iberian civ bonus starting wall. Remove/rename if the new one (above) is suficient (well, I think it is...) |
| 928 | // |
| 929 | // radius: A float seting the aproximate radius of the fortress |
| 930 | // maxBendOff: Optional, The maximum random bending offset of the wall elements |
| 931 | // NOTE: If maxBendOff > PI/3 the wall might not circumvent the center, if > PI/2 the wall might wind up in an infinite loop!!! |
| 932 | // wallPart: Optional, An array of wall element string, example: ["tower", "wall"] |
| 933 | // NOTE: Don't use wall elements with bending like corners! |
| 934 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 935 | function placeOrganicFortress(centerX, centerY, radius, playerId, wallPart, style, maxBendOff) |
| 936 | { |
| 937 | // Setup optional arguments to the default |
| 938 | if (wallPart === undefined) |
| 939 | wallPart = ['tower', 'wall', 'tower', 'entry', 'tower', 'wall']; |
| 940 | if (maxBendOff === undefined) |
| 941 | maxBendOff = 0; |
| 942 | // Check arguments for sane values |
| 943 | if (maxBendOff > PI/3 || maxBendOff < 0) |
| 944 | warn("placeOrganicFortress maxBendOff sould satisfy 0 < maxBendOff < PI/3 (~1) to ensure stability but it is: " + maxBendOff); |
| 945 | // Check wall part length against shortest theoretical total wall length (circle perimeter) |
| 946 | var wallPartLength = getWallLength(wallPart, style); |
| 947 | if (wallPartLength > PI*radius || wallPartLength <= 0) |
| 948 | warn("placeOrganicFortress: Given wall part is longer than half the circle perimeter of given radius: Half circle perimeter ~= " + round(PI*radius) +", wallPart total length ~= " + round(wallPartLength)); |
| 949 | // Setting up some variables |
783 | | placeLinearWall(centerX + x, centerY + y, centerX + targetX, centerY + targetY, ['wall', 'tower'], style, playerId, true); |
| 979 | // Close wall with simple linear wall |
| 980 | if (getDistance(centerX + x, centerY + y, centerX + targetX, centerY + targetY) > wallStyles[style]['wallLong'].width) |
| 981 | placeLinearWall(centerX + x, centerY + y, centerX + targetX, centerY + targetY, ['wall', 'tower'], style, playerId, true); |