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 |
10 | | // Adjust default fortress types |
11 | | // Add wall style 'roads' |
12 | | // Add trsures to 'others' |
| 6 | // Check if all wall placement methods work with wall elements with entity === undefined (some still might raise errors in that case) |
| 7 | // Rename wall elements to fit the 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/balanced default palisade fortress types matching civ default fortresses strength |
| 9 | // Perhaps add further wall elements cornerInHalf, cornerOutHalf (banding PI/4) 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 |
| 11 | // Adjust argument order to be always the same: |
| 12 | // Coordinates (center/start/target) |
| 13 | // Wall element arguments (wall/wallPart/fortressType/cornerElement) |
| 14 | // playerId (optional, default is 0/gaia) |
| 15 | // wallStyle (optional, default is the players civ) |
| 16 | // angle/orientation (optional, default is 0) |
| 17 | // other (all optional) arguments especially those hard to define (wallPartsAssortment, maybe make an own function for it) |
| 18 | // Some arguments don't clearly match to this concept: |
| 19 | // endWithFirst (wall or other) |
| 20 | // skipFirstWall (wall or other) |
| 21 | // gateOccurence (wall or other) |
| 22 | // numCorners (wall or other) |
| 23 | // skipFirstWall (wall or other) |
| 24 | // maxAngle (angle or other) |
| 25 | // maxBendOff (angle or other, unused ATM!!!) |
| 26 | // irregularity |
| 27 | // maxTrys |
| 28 | // Add trsures to wall style 'others' |
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) |
| 36 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 37 | // WallElement class definition |
| 38 | // |
| 39 | // type: Descriptive string, example: 'wall'. NOTE: Not really needed. Mainly for custom wall elements and to get the wall element type in code. |
| 40 | // entity: Optional. Template string to be placed, example: 'structures/cart_wall'. Default is undefined (No entity placed) |
| 41 | // angle: Optional. Placement angle so that 'outside' is 'right' (towards positive X like a unit placed with angle 0). Default is 0 (0*PI) |
| 42 | // width: Optional. The width it lengthens the wall, width because it's the needed space in a right angle to 'outside'. Default is 0 |
| 43 | // indent: Optional. The indentation means its drawn inside (positive values) or pushed outwards (negative values). Default is 0 |
| 44 | // bending: Optional. How the direction of the wall is changed after this element, positive is bending 'in' (counter clockwise like entity placement) |
| 45 | // |
| 46 | // NOTE: Bending is only used for fortresses and custom walls. Linear/circular walls walls use no/generic bending |
| 47 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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. |
78 | | function Fortress(type, wall, center) |
| 84 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 85 | // Fortress class definition |
| 86 | // |
| 87 | // A list would do for symetric fortresses but if 'getCenter' don't do sufficient the center can be set manually |
| 88 | // |
| 89 | // type Descriptive string, example: 'tiny'. Not really needed (WallTool.wallTypes['type string'] is used). Mainly for custom wall elements |
| 90 | // wall Optional. Array of wall element strings. Can be set afterwards. Default is an epty array. |
| 91 | // Example: ['entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'entrance', 'wall', 'cornerIn', 'wall', 'gate', 'wall', 'cornerIn', 'wall'] |
| 92 | // centerToFirstElement Optional. Array of 2 floats determinig the vector from the center to the first wall element. Default is undefined |
| 93 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 94 | function Fortress(type, wall, centerToFirstElement) |
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'... |
| 102 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 103 | // wallStyles data structure for default wall styles |
| 104 | // |
| 105 | // A wall style is an associative array with all wall elements of that style in it associated with the wall element type string |
| 106 | // wallStyles holds all the wall styles within an associative array with the civ string or another descriptive strings as key |
| 107 | // Examples: "athen", "rome_siege", "palisades", "fence", "road" |
| 108 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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) |
| 112 | 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}; |
| 113 | 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]); |
| 120 | wallStyles[style]['tower'] = new WallElement('tower', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); |
| 121 | wallStyles[style]['endLeft'] = new WallElement('endLeft', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades... |
| 122 | wallStyles[style]['endRight'] = new WallElement('endRight', 'structures/' + style + '_wall_tower', PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades... |
| 123 | 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 |
| 124 | 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 |
| 125 | wallStyles[style]['wallShort'] = new WallElement('wallShort', 'structures/' + style + '_wall_short', 0*PI, 2*wallScaleByType[style]); |
| 126 | wallStyles[style]['wall'] = new WallElement('wall', 'structures/' + style + '_wall_medium', 0*PI, 4*wallScaleByType[style]); |
| 127 | wallStyles[style]['wallMedium'] = new WallElement('wall', 'structures/' + style + '_wall_medium', 0*PI, 4*wallScaleByType[style]); |
| 128 | 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]); |
| 140 | wallStyles[style]['entryTower'] = new WallElement('entryTower', 'structures/' + civ + '_defense_tower', PI, gateWidth, -4*wallScaleByType[style]); |
| 141 | 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]); |
| 146 | wallStyles[style]['barracks'] = new WallElement('barracks', 'structures/' + civ + '_barracks', PI, 0, 4.5*wallScaleByType[style]); |
| 147 | wallStyles[style]['civilCentre'] = new WallElement('civilCentre', 'structures/' + civ + '_civil_centre', PI, 0, 4.5*wallScaleByType[style]); |
| 148 | wallStyles[style]['farmstead'] = new WallElement('farmstead', 'structures/' + civ + '_farmstead', PI, 0, 4.5*wallScaleByType[style]); |
| 149 | wallStyles[style]['field'] = new WallElement('field', 'structures/' + civ + '_field', PI, 0, 4.5*wallScaleByType[style]); |
| 150 | wallStyles[style]['fortress'] = new WallElement('fortress', 'structures/' + civ + '_fortress', PI, 0, 4.5*wallScaleByType[style]); |
| 151 | wallStyles[style]['house'] = new WallElement('house', 'structures/' + civ + '_house', PI, 0, 4.5*wallScaleByType[style]); |
| 152 | wallStyles[style]['market'] = new WallElement('market', 'structures/' + civ + '_market', PI, 0, 4.5*wallScaleByType[style]); |
| 153 | wallStyles[style]['mill'] = new WallElement('mill', 'structures/' + civ + '_mill', PI, 0, 4.5*wallScaleByType[style]); |
| 154 | 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]); |
| 156 | wallStyles[style]['space1'] = new WallElement('space1', undefined, 0*PI, wallScaleByType[style]); |
| 157 | wallStyles[style]['space2'] = new WallElement('space2', undefined, 0*PI, 2*wallScaleByType[style]); |
| 158 | wallStyles[style]['space3'] = new WallElement('space3', undefined, 0*PI, 3*wallScaleByType[style]); |
| 159 | wallStyles[style]['space4'] = new WallElement('space4', undefined, 0*PI, 4*wallScaleByType[style]); |
| 202 | // NOTE: This is not a wall style in the common sense. Use with care! |
| 203 | wallStyles['road'] = {}; |
| 204 | wallStyles['road']['short'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_short.xml", PI/2, 4.5); |
| 205 | wallStyles['road']['long'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_long.xml", PI/2, 9.5); |
| 206 | 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 |
| 207 | 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 |
| 208 | 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 |
| 209 | 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 |
| 210 | wallStyles['road']['start'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_end.xml", PI/2, 2); |
| 211 | wallStyles['road']['end'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_end.xml", -PI/2, 2); |
| 212 | wallStyles['road']['xStraight'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5); |
| 213 | wallStyles['road']['xLeft'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, PI/2); |
| 214 | wallStyles['road']['xRight'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, -PI/2); |
| 215 | wallStyles['road']['tLeft'] = new WallElement('road', "actor|props/special/eyecandy/road_temperate_intersect_T.xml", PI, 4.5, 1.25); |
| 216 | 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' |
| 243 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 244 | // fortressTypes data structure for some default fortress types |
| 245 | // |
| 246 | // A fortress type is just an instance of the fortress class with actually something in it |
| 247 | // fortressTypes holds all the fortressess within an associative array with a descriptive string as key (e.g. maching the map size) |
| 248 | // Eexamples: "tiny', "veryLarge" |
| 249 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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 | | |
269 | | // Setup some semi default fortresses for 'palisades' style |
| 286 | // Setup some better looking semi default fortresses for 'palisades' style |
287 | | /////////////////////////////////////////////////////////////////////////////// |
288 | | // Define some helper functions: getWallAlignment, getWallCenter, getWallLength |
289 | | /////////////////////////////////////////////////////////////////////////////// |
| 306 | // Add some "fortress types" for roads (will only work with style "road") |
| 307 | // ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft", "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"]; |
| 308 | var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"]; |
| 309 | fortressTypes['road01'] = new Fortress('road01', wall); |
| 310 | var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"]; |
| 311 | fortressTypes['road02'] = new Fortress('road02', wall); |
| 312 | var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"]; |
| 313 | fortressTypes['road03'] = new Fortress('road03', wall); |
| 314 | var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short", |
| 315 | "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"]; |
| 316 | fortressTypes['road04'] = new Fortress('road04', wall); |
| 317 | var wall = ["start", "tLeft", "short", "xRight", |
| 318 | "curveLeft", "xRight", "tRight", "cornerLeft", "tRight", |
| 319 | "curveLeft", "short", "tRight", "cornerLeft", "xRight", |
| 320 | "cornerLeft", "xRight", "short", "tRight", "curveLeft", "end"]; |
| 321 | 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 |
| 323 | |
| 324 | /////////////////////////////// |
| 325 | // Define some helper functions |
| 326 | /////////////////////////////// |
| 327 | |
| 328 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 329 | // getWallAlignment |
| 330 | // |
| 331 | // Returns a list of lists of most arguments needed to place the different wall elements for a given wall |
| 332 | // Placing the first wall element at startX/startY placed with angle given by orientation |
| 333 | // An alignement can be used to get the "center" of a "wall" (more likely used for fortresses) with getCenterToFirstElement |
| 334 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
336 | | // Get the center of a wall (mainly usefull for closed walls like fortresses) |
337 | | // Center calculation works like getting the center of mass assuming all wall elements have the same 'waight' |
338 | | // It returns the vector (array [x, y]) from the first wall element to the center |
339 | | function getWallCenter(alignment) |
| 376 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 377 | // getCenterToFirstElement |
| 378 | // |
| 379 | // Center calculation works like getting the center of mass assuming all wall elements have the same "waight" |
| 380 | // It returns the vector (array [x, y]) from the center to the first wall element |
| 381 | // Used to get centerToFirstElement of fortresses by default |
| 382 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 383 | function getCenterToFirstElement(alignment) |
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 |
| 417 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 418 | // placeWall |
| 419 | // |
| 420 | // Places a wall with wall elements attached to another like determined by WallElement properties. |
| 421 | // |
| 422 | // startX, startY Where the first wall element should be placed |
| 423 | // wall Array of wall element type strings. Example: ["endLeft", "wallLong", "tower", "wallLong", "endRight"] |
| 424 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 425 | // playerId Optional. Number of the player the wall will be placed for. Default is 0 (gaia) |
| 426 | // orientation Optional. Angle the first wall element is placed. Default is 0 |
| 427 | // 0 means 'outside' or 'front' of the wall is right (positive X) like placeObject |
| 428 | // It will then be build towards top/positive Y (if no bending wall elements like corners are used) |
| 429 | // Raising orientation means the wall is rotated counter-clockwise like placeObject |
| 430 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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) |
389 | | function placeCustomFortress(centerX, centerY, fortress, style, playerId, orientation, scipGetCenter) |
| 450 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 451 | // placeCustomFortress |
| 452 | // |
| 453 | // Place a fortress (mainly a closed wall build like placeWall) centered at centerX/centerY |
| 454 | // The fortress wall should always start with the main entrance (like 'entry' or 'gate') to get the orientation right (like placeObject) |
| 455 | // |
| 456 | // fortress An instance of Fortress with a wall defined |
| 457 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 458 | // playerId Optional. Number of the player the wall will be placed for. Default is 0 (gaia) |
| 459 | // orientation Optional. Angle the first wall element (should be a gate or entrance) is placed. Default is 0 |
| 460 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 461 | function placeCustomFortress(centerX, centerY, fortress, style, playerId, orientation) |
408 | | placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation, scipGetCenter); |
| 487 | // Setup optional arguments |
| 488 | type = (type || "tiny"); |
| 489 | playerId = (playerId || 0); |
| 490 | if (playerId == 0) |
| 491 | style = (style || "palisades"); |
| 492 | else |
| 493 | style = (style || g_MapSettings.PlayerData[playerId-1].Civ); |
| 494 | orientation = (orientation || 0); |
| 495 | // Call placeCustomFortress with the given arguments |
| 496 | placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation); |
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 |
| 499 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 500 | // placeLinearWall |
| 501 | // |
| 502 | // Places a straight wall from a given coordinate to an other repeatant using the wall parts. |
| 503 | // |
| 504 | // startX/startY Coordinate of the approximate beginning of the wall (Not the place of the first wall element) |
| 505 | // targetX/targetY Coordinate of the approximate ending of the wall (Not the place of the last wall element) |
| 506 | // wallPart Optional. An array of NON-BENDING wall element type strings. Default is ["tower", "wallLong"] |
| 507 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 508 | // playerId Optional. Integer number of the player. Default is 0 (gaia) |
| 509 | // endWithFirst Optional. A boolean value. If true the 1st wall element in the wallPart array will finalize the wall. Default is true |
| 510 | // |
| 511 | // TODO: Maybe add angle offset for more generic looking? |
| 512 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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 |
| 577 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 578 | // placeCircularWall |
| 579 | // |
| 580 | // Place a circular wall of repeatant wall elements given in the argument wallPart arround centerX/centerY with the given radius |
| 581 | // |
| 582 | // The wall is not necessarily closed depending on the optional argument maxAngle (better name?) |
| 583 | // NOTE: Don't use wall elements with bending like corners! |
| 584 | // TODO: Perhaps add eccentricity and maxBendOff functionality (untill now an unused argument) |
| 585 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
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) |
| 835 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 836 | // placeGenericFortress |
| 837 | // |
| 838 | // Places a generic fortress with towers at the edges connected with long walls and gates (entries untill gates work) |
| 839 | // This is the default Iberian civ bonus starting wall |
| 840 | // |
| 841 | // radius The approximate radius of the wall to be placed |
| 842 | // playerId Optional. Integer number of the player. Default is 0 (gaia) |
| 843 | // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia |
| 844 | // irregularity Optional. Float between 0 (circle) and 1 (very spiky), default is 1/2 |
| 845 | // gateOccurence Optional. Integer number, every n-th walls will be a gate instead. Default is 3 |
| 846 | // maxTrys Optional. How often the function tries to find a better fitting shape at max. Default is 100 |
| 847 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| 848 | 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++) |
| 850 | // Setup optional arguments |
| 851 | radius = (radius || 20); |
| 852 | playerId = (playerId || 0); |
| 853 | if (playerId == 0) |
| 854 | style = (style || "palisades"); |
| 855 | else |
| 856 | style = (style || g_MapSettings.PlayerData[playerId-1].Civ); |
| 857 | irregularity = (irregularity || 1/2); |
| 858 | gateOccurence = (gateOccurence || 3); |
| 859 | maxTrys = (maxTrys || 100); |
| 860 | // Setup some vars |
| 861 | var startAngle = randFloat(0, 2*PI); |
| 862 | var actualOffX = radius*cos(startAngle); |
| 863 | var actualOffY = radius*sin(startAngle); |
| 864 | var actualAngle = startAngle; |
| 865 | var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width; |
| 866 | // Searching for a well fitting point derivation |
| 867 | var tries = 0; |
| 868 | var bestPointDerivation = undefined; |
| 869 | var minOverlap = 1000; |
| 870 | var overlap = undefined; |
| 871 | while (tries < maxTrys && minOverlap > wallStyles[style]["tower"].width / 10) |
739 | | wallLength += wallStyles[style][wallPart[eleIndex]].width |
| 873 | var pointDerivation = []; |
| 874 | var distanceToTarget = 1000; |
| 875 | var targetReached = false; |
| 876 | while (!targetReached) |
| 877 | { |
| 878 | var indent = randFloat(-irregularity*pointDistance, irregularity*pointDistance); |
| 879 | var tmpAngle = getAngle(actualOffX, actualOffY, |
| 880 | (radius + indent)*cos(actualAngle + (pointDistance / radius)), |
| 881 | (radius + indent)*sin(actualAngle + (pointDistance / radius))); |
| 882 | actualOffX += pointDistance*cos(tmpAngle); |
| 883 | actualOffY += pointDistance*sin(tmpAngle); |
| 884 | actualAngle = getAngle(0, 0, actualOffX, actualOffY); |
| 885 | pointDerivation.push([actualOffX, actualOffY]); |
| 886 | distanceToTarget = getDistance(actualOffX, actualOffY, pointDerivation[0][0], pointDerivation[0][1]); |
| 887 | if ( pointDerivation.length > 3 && distanceToTarget < pointDistance) // Could be done better... |
| 888 | { |
| 889 | targetReached = true; |
| 890 | overlap = pointDistance - getDistance(pointDerivation[pointDerivation.length - 1][0], pointDerivation[pointDerivation.length - 1][1], pointDerivation[0][0], pointDerivation[0][1]); |
| 891 | if (overlap < minOverlap) |
| 892 | { |
| 893 | minOverlap = overlap; |
| 894 | bestPointDerivation = pointDerivation; |
| 895 | } |
| 896 | } |
| 897 | } |
| 898 | tries++; |
747 | | eleWidth = wallStyles[style][wallPart[eleIndex]].width; |
748 | | if (eleWidth < minEleWidth) |
749 | | minEleWidth = eleWidth; |
| 904 | var startX = centerX + bestPointDerivation[pointIndex][0]; |
| 905 | var startY = centerY + bestPointDerivation[pointIndex][1]; |
| 906 | var targetX = centerX + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][0]; |
| 907 | var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1]; |
| 908 | var angle = getAngle(startX, startY, targetX, targetY); |
| 909 | var wallElement = "wallLong"; |
| 910 | if ((pointIndex + 1) % gateOccurence == 0) |
| 911 | wallElement = "entry"; // Has to be changed to "gate" if gates work... |
| 912 | if (wallStyles[style][wallElement].entity) |
| 913 | { |
| 914 | placeObject(startX + (getDistance(startX, startY, targetX, targetY)/2)*cos(angle), // placeX |
| 915 | startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY |
| 916 | wallStyles[style][wallElement].entity, playerId, angle - PI/2 + wallStyles[style][wallElement].angle); |
| 917 | } |
| 918 | // Place tower |
| 919 | var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0]; |
| 920 | var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1]; |
| 921 | var angle = getAngle(startX, startY, targetX, targetY); |
| 922 | 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 | | |
753 | | var x = radius; |
754 | | var y = 0; |
755 | | var angle = 0; |
756 | | var targetX = radius; |
757 | | var targetY = 0; |
758 | | var targetReached = false; |
759 | | var eleIndex = 0; |
760 | | while (targetReached == false) |
761 | | { |
762 | | var wallElement = wallStyles[style][wallPart[eleIndex % wallPart.length]]; |
763 | | var eleWidth = wallElement.width - widthSafty; |
764 | | // Stabalized bendOff |
765 | | var actualRadius = getDistance(centerX, centerY, centerX + x, centerY + y); |
766 | | var bendOff = randFloat(-maxBendOff*radius/actualRadius, maxBendOff*actualRadius/radius); |
767 | | // Element width in radians |
768 | | var eleAngleWidth = eleWidth*cos(bendOff) / radius; // A/L = da/dl -> da = A * dl / L -> da = 2*PI * eleWidth / (2*PI * radius) -> da = eleWidth/radius |
769 | | var eleAngle = angle + eleAngleWidth/2 + bendOff; |
770 | | var placeX = x - eleWidth/2 * sin(eleAngle); |
771 | | var placeY = y + eleWidth/2 * cos(eleAngle); |
772 | | if (wallElement.entity) |
773 | | placeObject(centerX + placeX, centerY + placeY, wallElement.entity, playerId, eleAngle + wallElement.angle); |
774 | | x = placeX - eleWidth/2 * sin(eleAngle); |
775 | | y = placeY + eleWidth/2 * cos(eleAngle); |
776 | | angle += eleAngleWidth; |
777 | | if (eleIndex % wallPart.length == 0 && eleIndex > wallPart.length && (getDistance(x, y, targetX, targetY) < wallLength || angle > 2*PI)) |
778 | | targetReached = true; |
779 | | eleIndex++; |
780 | | // if (eleIndex == 10) |
781 | | // break; |
782 | | } |
783 | | placeLinearWall(centerX + x, centerY + y, centerX + targetX, centerY + targetY, ['wall', 'tower'], style, playerId, true); |