Ticket #2944: wallgen_additional_20150816.patch
File wallgen_additional_20150816.patch, 81.4 KB (added by , 9 years ago) |
---|
-
binaries/data/mods/public/globalscripts/Templates.js
function GetTemplateDataHelper(template, player) 251 251 "templates": { 252 252 "tower": template.WallSet.Templates.Tower, 253 253 "gate": template.WallSet.Templates.Gate, 254 "fort": template.WallSet.Templates.Fort || "structures/{civ}_fortress", 254 255 "long": template.WallSet.Templates.WallLong, 255 256 "medium": template.WallSet.Templates.WallMedium, 256 257 "short": template.WallSet.Templates.WallShort, … … function GetTemplateDataHelper(template, player) 258 259 "maxTowerOverlap": +template.WallSet.MaxTowerOverlap, 259 260 "minTowerOverlap": +template.WallSet.MinTowerOverlap, 260 261 }; 262 if (template.WallSet.Templates.WallEnd) 263 ret.wallSet.templates.end = template.WallSet.Templates.WallEnd; 264 if (template.WallSet.Templates.WallCurveQuarter) 265 ret.wallSet.templates.quarterCurve = template.WallSet.Templates.WallCurveQuarter; 266 if (template.WallSet.Templates.WallCurveEighth) 267 ret.wallSet.templates.eighthCurve = template.WallSet.Templates.WallCurveEighth; 261 268 } 262 269 263 270 if (template.WallPiece) 264 ret.wallPiece = {"length": +template.WallPiece.Length}; 271 ret.wallPiece = { 272 "length": +template.WallPiece.Length, 273 "angle": +(template.WallPiece.Orientation || 1) * Math.PI, 274 "indent": +(template.WallPiece.Indent || 0), 275 "bend": +(template.WallPiece.Bend || 0) * Math.PI, 276 }; 265 277 266 278 return ret; 267 279 } -
binaries/data/mods/public/maps/random/rmgen/library.js
4 4 ///////////////////////////////////////////////////////////////////////////////////////////// 5 5 6 6 const PI = Math.PI; 7 const TWO_PI = 2 * Math.PI; 7 const TWO_PI = 2 * Math.PI; // mathematically known as 'tau' 8 8 const TERRAIN_SEPARATOR = "|"; 9 9 const SEA_LEVEL = 160.0; 10 10 const CELL_SIZE = 4; -
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 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 // WallElement class definition 39 // 40 // Concept: If placed unrotated the wall's build direction is towards positive Y (top) with "outside" right (+X) and "inside" left (-X) like unrotated entities has their drop-points right (in rmgen) 41 // The build direction of the wall will be changed by corners (bending != 0) and so the "inside"/"outside" direction 42 // 43 // type Identification string. 44 // entPath Optional. Template entity path string of the entity to be placed, example: "structures/cart_wall_long". Default is undefined (No entity placed) 45 // angle Optional. Relative angle to the build direction. Default is 0 46 // width Optional. How far this wall element lengthens the wall (float), if unrotated the Y space needed. Default is 0 47 // indent Optional. The lateral indentation of the entity, drawn "inside" (positive values) or pushed "outside" (negative values). Default is 0 48 // bending Optional. How the build direction of the wall is changed after this element, positive is bending "in"/left/counter clockwise (like entity placement) 49 // NOTE: Bending is not supported by all placement functions (see there) 50 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 51 function WallElement(type, entPath, angle, width, indent, bending) 36 /** 37 * Set some globals for this module 38 */ 39 var g_WallStyles = {}; 40 var g_WallStyleList = []; 41 var g_CivData = getFullCivData(); 42 var g_CivList = Object.keys(g_CivData); 43 var g_FortressTypes = {}; 44 var g_FortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"]; 45 46 /** 47 * Basic Initialisation 48 * 49 * Fetches wallsets from {civ}.json files, and then uses them to load 50 * basic wall elements 51 */ 52 for (let civ of g_CivList) 52 53 { 53 this.type = type; 54 this.entPath = entPath; 55 this.angle = (angle !== undefined) ? angle : 0; 56 this.width = (width !== undefined) ? width : 0; 57 this.indent = (indent !== undefined) ? indent : 0; 58 this.bending = (bending !== undefined) ? bending : 0; 54 let civInfo = g_CivData[civ]; 55 if (!civInfo.WallSets) 56 continue; 57 58 for (let path of civInfo.WallSets) 59 { 60 let style = path.split("/")[1].split("_"); 61 style = (style[0]=="wallset") ? style[1] : style[0]+"_"+style[2]; 62 63 if (g_WallStyleList.indexOf(style) == -1) 64 { 65 g_WallStyleList.push(style); 66 g_WallStyles[style] = {}; 67 let wallset = GetTemplateDataHelper(RMS.GetTemplate(path)).wallSet; 68 for (let element in wallset.templates) 69 setWallElement(style, element, wallset.templates[element].replace("{civ}",civ)) 70 g_WallStyles[style]["@overlap"] = wallset.minTowerOverlap * getWallElement(style, "tower").length; 71 } 72 } 59 73 } 60 74 61 75 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … function WallElement(type, entPath, angle, width, indent, bending) 72 86 function Fortress(type, wall, centerToFirstElement) 73 87 { 74 88 this.type = type; 75 this.wall = (wall !== undefined) ? wall :[];76 this.centerToFirstElement = undefined;89 this.wall = wall || []; 90 this.centerToFirstElement = centerToFirstElement || undefined; 77 91 } 78 92 79 80 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////81 // wallStyles data structure for default wall styles82 //83 // A wall style is an associative array with all wall elements of that style in it associated with the wall element type string84 // wallStyles holds all the wall styles within an associative array with the civ string or another descriptive strings as key85 // Examples: "athen", "rome_siege", "palisades", "fence", "road"86 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////87 var wallStyles = {};88 89 // Get wall element width by template file path and angle90 function getTemplateWidthByAngle(entPath, angle)91 {92 var template = RMS.GetTemplate(entPath);93 var width = getTemplateValue(entPath, ["WallPiece", "Length"]) / CELL_SIZE;94 95 return width;96 }97 98 // Add new WallElement by it's properties99 function addNewWallElement(style, type, angle)100 {101 var templatePath = "structures/" + style + "_" + type102 wallStyles[style][type] = new WallElement(type, templatePath, angle, getTemplateWidthByAngle(templatePath, angle));103 }104 105 // Find all wall sets by civ to be then put into wallStyles106 var entitiesByCiv = {};107 var civList = getCivList();108 for (var i = 0; i < civList.length; i++)109 {110 var civ = civList[i];111 var templatePathList = getTempatePathList(civ);112 entitiesByCiv[civ] = templatePathList;113 }114 115 // Generic civ dependent wall style definition. Some, e.g. "rome_siege" needs tweaking...116 var wallScaleByType = {}; // To be removed TODO117 var civData = getFullCivData();118 for (var i = 0; i < civList.length; i++)119 {120 var civ = civList[i];121 var wallSets = civData[civ].WallSets;122 if (wallSets.hasOwnProperty("Stone"))123 wallScaleByType[civ] = wallSets.Stone.Scale;124 }125 // Non-civ but civ specific wall styles126 wallScaleByType.rome_siege = 1.5;127 for (var style in wallScaleByType)128 {129 var civ = style;130 if (style == "rome_siege")131 civ = "rome";132 wallStyles[style] = {};133 // Default wall elements134 var templatePath = "structures/" + style + "_wall_tower";135 var angle = PI;136 var width = getTemplateWidthByAngle(templatePath, angle); // DEBUG137 log("getTemplateWidthByAngle(" + templatePath + ") = " + width + ", used to be width = " + wallScaleByType[style]); // DEBUG138 // wallStyles[style]["tower"] = new WallElement("tower", templatePath, angle, width);//wallScaleByType[style]);139 addNewWallElement(style, "wall_tower", PI);140 wallStyles[style]["tower"] = wallStyles[style]["wall_tower"]; // Shortcut141 142 wallStyles[style]["endLeft"] = new WallElement("endLeft", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades...143 wallStyles[style]["endRight"] = new WallElement("endRight", "structures/" + style + "_wall_tower", PI, wallScaleByType[style]); // Same as tower. To be compatible with palisades...144 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/3145 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/3146 147 var templatePath = "structures/" + style + "_wall_short"; // DEBUG148 var angle = 0*PI; // DEBUG149 var width = getTemplateWidthByAngle(templatePath, angle); // DEBUG150 log("getTemplateWidthByAngle(" + templatePath + ") = " + width + ", used to be width = " + 2*wallScaleByType[style]); // DEBUG151 wallStyles[style]["wallShort"] = new WallElement("wallShort", "structures/" + style + "_wall_short", 0*PI, 2*wallScaleByType[style]);152 153 var templatePath = "structures/" + style + "_wall_medium"; // DEBUG154 var angle = 0*PI; // DEBUG155 var width = getTemplateWidthByAngle(templatePath, angle); // DEBUG156 log("getTemplateWidthByAngle(" + templatePath + ") = " + width + ", used to be width = " + 4*wallScaleByType[style]); // DEBUG157 wallStyles[style]["wall"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);158 159 wallStyles[style]["wallMedium"] = new WallElement("wall", "structures/" + style + "_wall_medium", 0*PI, 4*wallScaleByType[style]);160 161 var templatePath = "structures/" + style + "_wall_long"; // DEBUG162 var angle = 0*PI; // DEBUG163 var width = getTemplateWidthByAngle(templatePath, angle); // DEBUG164 log("getTemplateWidthByAngle(" + templatePath + ") = " + width + ", used to be width = " + 6*wallScaleByType[style]); // DEBUG165 wallStyles[style]["wallLong"] = new WallElement("wallLong", "structures/" + style + "_wall_long", 0*PI, 6*wallScaleByType[style]);166 167 // Gate and entrance wall elements168 var gateWidth = 6*wallScaleByType[style];169 170 var templatePath = "structures/" + style + "_wall_gate"; // DEBUG171 var angle = PI; // DEBUG172 var width = getTemplateWidthByAngle(templatePath, angle); // DEBUG173 log("getTemplateWidthByAngle(" + templatePath + ") = " + width + ", used to be width = " + 6*wallScaleByType[style]); // DEBUG174 wallStyles[style]["gate"] = new WallElement("gate", "structures/" + style + "_wall_gate", PI, gateWidth);175 176 wallStyles[style]["entry"] = new WallElement("entry", undefined, 0*PI, gateWidth);177 wallStyles[style]["entryTower"] = new WallElement("entryTower", "structures/" + civ + "_defense_tower", PI, gateWidth, -4*wallScaleByType[style]);178 wallStyles[style]["entryFort"] = new WallElement("entryFort", "structures/" + civ + "_fortress", 0*PI, 8*wallScaleByType[style], 6*wallScaleByType[style]);179 // Defensive wall elements with 0 width outside the wall180 wallStyles[style]["outpost"] = new WallElement("outpost", "structures/" + civ + "_outpost", PI, 0, -4*wallScaleByType[style]);181 wallStyles[style]["defenseTower"] = new WallElement("defenseTower", "structures/" + civ + "_defense_tower", PI, 0, -4*wallScaleByType[style]);182 // Base buildings wall elements with 0 width inside the wall183 wallStyles[style]["barracks"] = new WallElement("barracks", "structures/" + civ + "_barracks", PI, 0, 4.5*wallScaleByType[style]);184 wallStyles[style]["civilCentre"] = new WallElement("civilCentre", "structures/" + civ + "_civil_centre", PI, 0, 4.5*wallScaleByType[style]);185 wallStyles[style]["farmstead"] = new WallElement("farmstead", "structures/" + civ + "_farmstead", PI, 0, 4.5*wallScaleByType[style]);186 wallStyles[style]["field"] = new WallElement("field", "structures/" + civ + "_field", PI, 0, 4.5*wallScaleByType[style]);187 wallStyles[style]["fortress"] = new WallElement("fortress", "structures/" + civ + "_fortress", PI, 0, 4.5*wallScaleByType[style]);188 wallStyles[style]["house"] = new WallElement("house", "structures/" + civ + "_house", PI, 0, 4.5*wallScaleByType[style]);189 wallStyles[style]["market"] = new WallElement("market", "structures/" + civ + "_market", PI, 0, 4.5*wallScaleByType[style]);190 wallStyles[style]["storehouse"] = new WallElement("storehouse", "structures/" + civ + "_storehouse", PI, 0, 4.5*wallScaleByType[style]);191 wallStyles[style]["temple"] = new WallElement("temple", "structures/" + civ + "_temple", PI, 0, 4.5*wallScaleByType[style]);192 // Generic space/gap wall elements193 wallStyles[style]["space1"] = new WallElement("space1", undefined, 0*PI, wallScaleByType[style]);194 wallStyles[style]["space2"] = new WallElement("space2", undefined, 0*PI, 2*wallScaleByType[style]);195 wallStyles[style]["space3"] = new WallElement("space3", undefined, 0*PI, 3*wallScaleByType[style]);196 wallStyles[style]["space4"] = new WallElement("space4", undefined, 0*PI, 4*wallScaleByType[style]);197 }198 // Adjust "rome_siege" style199 wallStyles["rome_siege"]["house"] = new WallElement("house", "structures/rome_tent", PI, 0, 4);200 201 // Add special wall styles not well to implement generic (and to show how custom styles can be added)202 203 // Add wall style "palisades"204 wallScaleByType["palisades"] = 0.55;205 wallStyles["palisades"] = {};206 wallStyles["palisades"]["wall"] = new WallElement("wall", "other/palisades_rocks_medium", 0*PI, 2.3);207 wallStyles["palisades"]["wallMedium"] = new WallElement("wall", "other/palisades_rocks_medium", 0*PI, 2.3);208 wallStyles["palisades"]["wallLong"] = new WallElement("wall", "other/palisades_rocks_long", 0*PI, 3.5);209 wallStyles["palisades"]["wallShort"] = new WallElement("wall", "other/palisades_rocks_short", 0*PI, 1.2);210 wallStyles["palisades"]["tower"] = new WallElement("tower", "other/palisades_rocks_tower", -PI/2, 0.7);211 // wallStyles["palisades"]["wallFort"] = new WallElement("wallFort", "other/palisades_rocks_fort", PI, 1.7);212 wallStyles["palisades"]["gate"] = new WallElement("gate", "other/palisades_rocks_gate", PI, 3.6);213 wallStyles["palisades"]["entry"] = new WallElement("entry", undefined, wallStyles["palisades"]["gate"].angle, wallStyles["palisades"]["gate"].width);214 wallStyles["palisades"]["entryTower"] = new WallElement("entryTower", "other/palisades_rocks_watchtower", 0*PI, wallStyles["palisades"]["gate"].width, -3);215 wallStyles["palisades"]["entryFort"] = new WallElement("entryFort", "other/palisades_rocks_fort", PI, 6, 3);216 wallStyles["palisades"]["cornerIn"] = new WallElement("cornerIn", "other/palisades_rocks_curve", 3*PI/4, 2.1, 0.7, PI/2);217 wallStyles["palisades"]["cornerOut"] = new WallElement("cornerOut", "other/palisades_rocks_curve", 5*PI/4, 2.1, -0.7, -PI/2);218 wallStyles["palisades"]["outpost"] = new WallElement("outpost", "other/palisades_rocks_outpost", PI, 0, -2);219 wallStyles["palisades"]["house"] = new WallElement("house", "other/celt_hut", PI, 0, 5);220 wallStyles["palisades"]["barracks"] = new WallElement("barracks", "structures/gaul_tavern", PI, 0, 5);221 wallStyles["palisades"]["endRight"] = new WallElement("endRight", "other/palisades_rocks_end", -PI/2, 0.2);222 wallStyles["palisades"]["endLeft"] = new WallElement("endLeft", "other/palisades_rocks_end", PI/2, 0.2);223 224 // Add special wall style "road"225 // NOTE: This is not a wall style in the common sense. Use with care!226 wallStyles["road"] = {};227 wallStyles["road"]["short"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_short.xml", PI/2, 4.5);228 wallStyles["road"]["long"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_long.xml", PI/2, 9.5);229 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/corner230 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/corner231 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/corner232 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/corner233 wallStyles["road"]["start"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_end.xml", PI/2, 2);234 wallStyles["road"]["end"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_end.xml", -PI/2, 2);235 wallStyles["road"]["xStraight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5);236 wallStyles["road"]["xLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, PI/2);237 wallStyles["road"]["xRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_x.xml", 0*PI, 4.5, 0, -PI/2);238 wallStyles["road"]["tLeft"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_T.xml", PI, 4.5, 1.25);239 wallStyles["road"]["tRight"] = new WallElement("road", "actor|props/special/eyecandy/road_temperate_intersect_T.xml", 0*PI, 4.5, -1.25);240 241 93 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 242 // fortressTypes data structure for some default fortress types94 // g_FortressTypes data structure for some default fortress types (defined above) 243 95 // 244 96 // A fortress type is just an instance of the Fortress class with actually something in it 245 97 // fortressTypes holds all the fortresses within an associative array with a descriptive string as key (e.g. matching the map size) 246 98 // Examples: "tiny", "veryLarge" 247 99 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 248 var fortressTypes = {}; 249 // Setup some default fortress types 250 // Add fortress type "tiny" 251 fortressTypes["tiny"] = new Fortress("tiny"); 252 var wallPart = ["gate", "tower", "wallShort", "cornerIn", "wallShort", "tower"]; 253 fortressTypes["tiny"].wall = wallPart.concat(wallPart, wallPart, wallPart); 254 // Add fortress type "small" 255 fortressTypes["small"] = new Fortress("small"); 256 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "tower"]; 257 fortressTypes["small"].wall = wallPart.concat(wallPart, wallPart, wallPart); 258 // Add fortress type "medium" 259 fortressTypes["medium"] = new Fortress("medium"); 260 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "tower"]; 261 fortressTypes["medium"].wall = wallPart.concat(wallPart, wallPart, wallPart); 262 // Add fortress type "normal" 263 fortressTypes["normal"] = new Fortress("normal"); 264 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "cornerOut", "wall", "cornerIn", "wall", "tower"]; 265 fortressTypes["normal"].wall = wallPart.concat(wallPart, wallPart, wallPart); 266 // Add fortress type "large" 267 fortressTypes["large"] = new Fortress("large"); 268 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "tower"]; 269 fortressTypes["large"].wall = wallPart.concat(wallPart, wallPart, wallPart); 270 // Add fortress type "veryLarge" 271 fortressTypes["veryLarge"] = new Fortress("veryLarge"); 272 var wallPart = ["gate", "tower", "wall", "cornerIn", "wall", "cornerOut", "wallLong", "cornerIn", "wallLong", "cornerOut", "wall", "cornerIn", "wall", "tower"]; 273 fortressTypes["veryLarge"].wall = wallPart.concat(wallPart, wallPart, wallPart); 274 // Add fortress type "giant" 275 fortressTypes["giant"] = new Fortress("giant"); 276 var wallPart = ["gate", "tower", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "cornerOut", "wallLong", "cornerIn", "wallLong", "tower"]; 277 fortressTypes["giant"].wall = wallPart.concat(wallPart, wallPart, wallPart); 100 101 // Set some default fortress types 102 for (let key of g_FortressTypeKeys) 103 g_FortressTypes[key] = new Fortress(key); 104 105 g_FortressTypes["tiny"].wall = ["gate", "tower", "short", "cornerIn", "short", "tower"]; 106 g_FortressTypes["small"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "tower"]; 107 g_FortressTypes["medium"].wall = ["gate", "tower", "long", "cornerIn", "long", "tower"]; 108 g_FortressTypes["normal"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "cornerOut", "medium", "cornerIn", "medium", "tower"]; 109 g_FortressTypes["large"].wall = ["gate", "tower", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "tower"]; 110 g_FortressTypes["veryLarge"].wall = ["gate", "tower", "medium", "cornerIn", "medium", "cornerOut", "long", "cornerIn", "long", "cornerOut", "medium", "cornerIn", "medium", "tower"]; 111 g_FortressTypes["giant"].wall = ["gate", "tower", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "cornerOut", "long", "cornerIn", "long", "tower"]; 112 113 for (let type in g_FortressTypes) 114 { 115 let wallPart = g_FortressTypes[type].wall; 116 g_FortressTypes[type].wall = wallPart.concat(wallPart, wallPart, wallPart); 117 } 278 118 279 119 // Setup some better looking semi default fortresses for "palisades" style 280 var fortressTypeKeys = ["tiny", "small", "medium", "normal", "large", "veryLarge", "giant"]; 281 for (var i = 0; i < fortressTypeKeys.length; i++) 120 for (let fortType of g_FortressTypeKeys) 282 121 { 283 var newKey = fort ressTypeKeys[i]+ "Palisades";284 var oldWall = fortressTypes[fortressTypeKeys[i]].wall;285 fortressTypes[newKey] = new Fortress(newKey);122 var newKey = fortType + "Palisades"; 123 var oldWall = g_FortressTypes[fortType].wall; 124 g_FortressTypes[newKey] = new Fortress(newKey); 286 125 var fillTowersBetween = ["wallShort", "wall", "wallLong", "endLeft", "endRight", "cornerIn", "cornerOut"]; 287 126 for (var j = 0; j < oldWall.length; j++) 288 127 { 289 fortressTypes[newKey].wall.push(oldWall[j]); // Only works if the first element is not in fillTowersBetween (e.g. entry or gate like it should be)128 g_FortressTypes[newKey].wall.push(oldWall[j]); // Only works if the first element is not in fillTowersBetween (e.g. entry or gate like it should be) 290 129 if (j+1 < oldWall.length) 291 130 if (fillTowersBetween.indexOf(oldWall[j]) > -1 && fillTowersBetween.indexOf(oldWall[j+1]) > -1) // ... > -1 means "exists" here 292 fortressTypes[newKey].wall.push("tower");131 g_FortressTypes[newKey].wall.push("tower"); 293 132 } 294 133 } 295 134 296 135 // Setup some balanced (to civ type fortresses) semi default fortresses for "palisades" style 297 136 // TODO 298 137 299 // Add some "fortress types" for roads (will only work with style "road")300 // ["start", "short", "xRight", "xLeft", "cornerLeft", "xStraight", "long", "xLeft", "xRight", "cornerRight", "tRight", "tLeft", "xRight", "xLeft", "curveLeft", "xStraight", "curveRight", "end"];301 var wall = ["short", "curveLeft", "short", "curveLeft", "short", "curveLeft", "short", "curveLeft"];302 fortressTypes["road01"] = new Fortress("road01", wall);303 var wall = ["short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft", "short", "cornerLeft"];304 fortressTypes["road02"] = new Fortress("road02", wall);305 var wall = ["xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft", "xStraight", "curveLeft"];306 fortressTypes["road03"] = new Fortress("road03", wall);307 var wall = ["start", "curveLeft", "tRight", "cornerLeft", "tRight", "curveRight", "short", "xRight", "curveLeft", "xRight", "short", "cornerLeft", "tRight", "short",308 "curveLeft", "short", "tRight", "cornerLeft", "short", "xRight", "curveLeft", "xRight", "short", "curveRight", "tRight", "cornerLeft", "tRight", "curveLeft", "end"];309 fortressTypes["road04"] = new Fortress("road04", wall);310 var wall = ["start", "tLeft", "short", "xRight",311 "curveLeft", "xRight", "tRight", "cornerLeft", "tRight",312 "curveLeft", "short", "tRight", "cornerLeft", "xRight",313 "cornerLeft", "xRight", "short", "tRight", "curveLeft", "end"];314 fortressTypes["road05"] = new Fortress("road05", wall);315 316 138 317 139 /////////////////////////////// 318 140 // Define some helper functions 319 141 /////////////////////////////// 320 142 143 /** 144 * Get a wall element of a style. 145 * 146 * If the element requested is unknown, the function attempts to derive 147 * it either from another element, or from a template or whatever. 148 * 149 * @param style The style to which this element comes from 150 * @param element The element to fetch 151 * @return The wall element requested. Or a tower element. 152 */ 153 function getWallElement(style="athen_stone", element) 154 { 155 if (g_WallStyleList.indexOf(style) < 0) 156 { 157 error("getWallElement: Style '"+style+"' not recognised. (Falling back to '" + FALLBACK_CIV + "_stone'.)"); 158 style = FALLBACK_CIV + "_stone"; 159 } 160 if (g_WallStyles[style][element]) 161 return g_WallStyles[style][element]; 162 163 // Attempt to derive any unknown elements. 164 // Defaults to a wall tower piece 165 var wallset = g_WallStyles[style]; 166 var civ = style.split("_")[0]; 167 var ret = clone(wallset.tower); 168 169 // We use clone() so we don't change the attributes of the object we're referencing 170 switch (element) 171 { 172 173 case "quarterCurve": 174 ret.angle += PI/4; 175 ret.bend = PI/2; 176 break; 177 178 case "eighthCurve": 179 ret.angle += PI/8; 180 ret.bend = PI/4; 181 break; 182 183 case "cornerIn": 184 if (wallset.quarterCurve) 185 ret = clone(wallset.quarterCurve); 186 else 187 { 188 ret.angle += PI/4 189 ret.indent = ret.length * 0.25; 190 ret.length = 0; 191 } 192 ret.bend = PI/2; 193 break; 194 195 case "cornerOut": 196 if (wallset.quarterCurve) 197 { 198 ret = clone(wallset.quarterCurve); 199 ret.angle += PI/2; 200 ret.indent -= ret.indent*2; 201 } 202 else 203 { 204 ret.angle -= PI/4; 205 ret.length *= 0.71; 206 } 207 ret.bend = -PI/2; 208 break; 209 210 case "wallShort": 211 warn("getWallElement: Deprecated use of 'wallShort' (please use 'short')"); 212 ret = clone(wallset.short); 213 break; 214 215 case "wallMedium": 216 case "wall": 217 warn("getWallElement: Deprecated use of '"+element+"' (please use 'medium')"); 218 ret = clone(wallset.medium); 219 break; 220 221 case "wallLong": 222 warn("getWallElement: Deprecated use of 'wallLong' (please use 'long')"); 223 ret = clone(wallset.long); 224 break; 225 226 case "entry": 227 ret.entPath = undefined; 228 ret.length = clone(g_WallStyles[style].gate.length); 229 break; 230 231 case "entryTower": 232 ret.entPath = (g_CivList.indexOf(civ) > -1) ? "structures/"+civ+"_defense_tower" : "other/palisades_rocks_watchtower"; 233 ret.indent = ret.length * -3; 234 ret.length = clone(g_WallStyles[style].gate.length); 235 break; 236 237 case "entryFort": 238 ret = clone(g_WallStyles[style].fort); 239 ret.angle -= PI; 240 ret.length *= 1.5; 241 ret.indent = ret.length; 242 break; 243 244 case "endLeft": 245 warn("getWallElement: Deprecated use of 'endLeft' (please use 'start')"); 246 case "start": 247 if (wallset.end) 248 { 249 ret = clone(wallset.end); 250 ret.angle += PI; 251 } 252 break; 253 254 case "endRight": 255 warn("getWallElement: Deprecated use of 'endRight' (please use 'start')"); 256 case "end": 257 if (wallset.end) 258 ret = clone(wallset.end); 259 break; 260 261 default: 262 // See if it's a structure (ie. house, barracks) 263 if (g_CivList.indexOf(civ) == -1) 264 civ = FALLBACK_CIV; 265 var entPath = "structures/"+civ+"_"+element; 266 if (RMS.TemplateExists(entPath)) 267 { 268 if (["outpost", "defense_tower"].indexOf(element) > -1) 269 ret.indent = ret.length * -3; 270 else 271 ret.indent = ret.length * 3.5; 272 ret.entPath = entPath; 273 ret.length = 0; 274 } 275 else if (element.slice(0.3) === "gap") 276 { 277 ret.entPath = undefined; 278 ret.angle = 0; 279 ret.length = +element.slice(4); 280 } 281 else if (element.slice(0,4) === "turn") 282 { 283 ret.entPath = undefined; 284 ret.angle = PI/2; 285 ret.length = 0; 286 if (element.slice(5) === "out") 287 ret.angle -= ret.angle; 288 } 289 else 290 warn("Unrecognised wall element: "+element+" ("+ style+"). Defaulting to 'tower'."); 291 } 292 293 // cache to save having to calculate this element again 294 g_WallStyles[style][element] = ret; 295 296 return ret; 297 } 298 299 /** 300 * Set a wall element of a style. 301 * 302 * @param style The style to which this element belongs 303 * @param element The element to add 304 * @param path The template path to read values from 305 */ 306 function setWallElement(style, element, path) 307 { 308 var template = RMS.GetTemplate(path); 309 template = GetTemplateDataHelper(template); 310 311 if (!g_WallStyles[style]) 312 g_WallStyles[style] = {}; 313 314 var length = (template.wallPiece) ? template.wallPiece.length : template.obstruction.shape.width; 315 g_WallStyles[style][element] = { 316 "entPath": path, 317 "angle": (template.wallPiece) ? template.wallPiece.angle : PI, 318 "length": length / CELL_SIZE, 319 "indent": (template.wallPiece) ? template.wallPiece.indent / CELL_SIZE : 0, 320 "bend": (template.wallPiece) ? template.wallPiece.bend : 0 321 }; 322 } 323 321 324 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 322 325 // getWallAlignment 323 326 // … … fortressTypes["road05"] = new Fortress("road05", wall); 325 328 // Placing the first wall element at startX/startY placed with an angle given by orientation 326 329 // An alignment can be used to get the "center" of a "wall" (more likely used for fortresses) with getCenterToFirstElement 327 330 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 328 function getWallAlignment(startX, startY, wall , style, orientation)331 function getWallAlignment(startX, startY, wall=[], style="athen_stone", orientation=0) 329 332 { 330 // Graciously handle arguments331 if (wall === undefined)332 wall = [];333 if (!wallStyles.hasOwnProperty(style))334 {335 warn("Function getWallAlignment: Unknown style: " + style + ' (falling back to "athen")');336 style = "athen";337 }338 orientation = (orientation || 0);339 340 333 var alignment = []; 341 334 var wallX = startX; 342 335 var wallY = startY; 336 343 337 for (var i = 0; i < wall.length; i++) 344 338 { 345 var element = wallStyles[style][wall[i]];339 var element = getWallElement(style, wall[i]); 346 340 if (element === undefined && i == 0) 347 warn("No valid wall element: style = " + style + ", wall[" + i + "] = " + wall[i] + ", wallStyles[" + style + "][wall[" + i + "]] = " + wallStyles[style][wall[i]] + ", element = " + element + ", wall = " + wall); 341 { 342 warn("Not a valid wall element: style = " + style + ", wall[" +i+ "] = " +wall[i]+ "; .entPath = " +element.entPath+ ", .length = " +element.length+ ", .angle = " +element.angle+ ", .indent = " +element.indent+ ", .bend = " +element.bend); 343 continue; 344 } 345 348 346 // Indentation 349 347 var placeX = wallX - element.indent * cos(orientation); 350 348 var placeY = wallY - element.indent * sin(orientation); 349 351 350 // Add wall elements entity placement arguments to the alignment 352 351 alignment.push({"x": placeX, "y": placeY, "entPath": element.entPath, "angle":orientation + element.angle}); 352 353 353 // Preset vars for the next wall element 354 354 if (i+1 < wall.length) 355 355 { 356 orientation += element.bend ing;357 var nextElement = wallStyles[style][wall[i+1]];356 orientation += element.bend; 357 var nextElement = getWallElement(style, wall[i+1]); 358 358 if (nextElement === undefined) 359 warn("No valid wall element: style = " + style + ", wall[" + (i+1) + "] = " + wall[i+1] + ", wallStyles[" + style + "][wall[" + (i+1) + "]] = " + wallStyles[style][wall[i+1]] + ", nextElement = " + uneval(nextElement) + ", wall = " + wall); 360 var distance = (element.width + nextElement.width)/2; 359 { 360 warn("Not a valid wall element: style = " + style + ", wall[" +(i+1)+ "] = " +wall[i+1]+ "; .entPath = " +nextElement.entPath+ ", .length = " +nextElement.length+ ", .angle = " +nextElement.angle+ ", .indent = " +nextElement.indent+ ", .bend = " +nextElement.bend); 361 continue; 362 } 363 364 var distance = (element.length + nextElement.length)/2 - getOverlap(style); 361 365 // Corrections for elements with indent AND bending 362 366 var indent = element.indent; 363 var bend ing = element.bending;364 if (bend ing!== 0 && indent !== 0)367 var bend = element.bend; 368 if (bend !== 0 && indent !== 0) 365 369 { 366 370 // Indent correction to adjust distance 367 distance += indent*sin(bend ing);371 distance += indent*sin(bend); 368 372 // Indent correction to normalize indentation 369 373 wallX += indent * cos(orientation); 370 374 wallY += indent * sin(orientation); 371 375 } 376 372 377 // Set the next coordinates of the next element in the wall without indentation adjustment 373 378 wallX -= distance * sin(orientation); 374 379 wallY += distance * cos(orientation); … … function getCenterToFirstElement(alignment) 400 405 // getWallLength 401 406 // 402 407 // NOTE: Does not support bending wall elements like corners! 403 // e.g. used by placeIrregularPolygonalWall404 408 ////////////////////////////////////////////////////////////////// 405 function getWallLength( wall, style)409 function getWallLength(style, wall=[]) 406 410 { 407 411 // Graciously handle arguments 408 if (wall === undefined) 409 wall = []; 410 if (!wallStyles.hasOwnProperty(style)) 412 if (g_WallStyleList.indexOf(style) < 0) 411 413 { 412 warn(" Function getWallLength: Unknown style: " + style + ' (falling back to "athen")');413 style = "athen";414 warn("getWallLength: Unknown style: '" + style + "'. (Falling back to '" + FALLBACK_CIV + "_stone')."); 415 style = FALLBACK_CIV +"_stone"; 414 416 } 415 417 416 418 var length = 0; 417 for (var i = 0; i < wall.length; i++)418 {419 length += wallStyles[style][wall[i]].width;420 } 419 var overlap = getOverlap(style); 420 for (let element of wall) 421 length += getWallElement(style, element).length - overlap; 422 421 423 return length; 422 424 } 423 425 426 function getOverlap(style) 427 { 428 if (!style || !g_WallStyles[style]) 429 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 430 return g_WallStyles[style]["@overlap"]; 431 } 432 424 433 425 434 ///////////////////////////////////////////// 426 435 // Define the different wall placer functions … … function getWallLength(wall, style) 440 449 // It will then be build towards top/positive Y (if no bending wall elements like corners are used) 441 450 // Raising orientation means the wall is rotated counter-clockwise like placeObject 442 451 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 443 function placeWall(startX, startY, wall , style, playerId, orientation)452 function placeWall(startX, startY, wall=[], style, playerId=0, orientation=0) 444 453 { 445 // Graciously handle arguments 446 if (wall === undefined) 447 wall = []; 448 playerId = (playerId || 0); 449 if (!wallStyles.hasOwnProperty(style)) 450 { 451 if (playerId == 0) 452 style = (style || "palisades"); 453 else 454 style = (getCivCode(playerId-1)); 455 } 456 orientation = (orientation || 0); 454 if (!startX || !startY) 455 return; 456 457 if (!style || g_WallStyleList.indexOf(style) == -1) 458 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 457 459 458 460 // Get wall alignment 459 461 var AM = getWallAlignment(startX, startY, wall, style, orientation); 462 460 463 // Place the wall 461 464 for (var iWall = 0; iWall < wall.length; iWall++) 462 465 { … … function placeWall(startX, startY, wall, style, playerId, orientation) 477 480 // playerId Optional. Number of the player the wall will be placed for. Default is 0 (gaia) 478 481 // orientation Optional. Angle the first wall element (should be a gate or entrance) is placed. Default is 0 479 482 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 480 function placeCustomFortress(centerX, centerY, fortress, style, playerId , orientation)483 function placeCustomFortress(centerX, centerY, fortress, style, playerId=0, orientation=0) 481 484 { 482 485 // Graciously handle arguments 483 fortress = (fortress || fortressTypes["medium"]); 484 playerId = (playerId || 0); 485 if (!wallStyles.hasOwnProperty(style)) 486 { 487 if (playerId == 0) 488 style = (style || "palisades"); 489 else 490 style = (getCivCode(playerId-1)); 491 } 492 orientation = (orientation || 0); 486 fortress = fortress || g_FortressTypes["medium"]; 487 if (!style || !g_WallStyles[style]) 488 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 493 489 494 490 // Calculate center if fortress.centerToFirstElement is undefined (default) 495 491 var centerToFirstElement = fortress.centerToFirstElement; … … function placeCustomFortress(centerX, centerY, fortress, style, playerId, orient 506 502 // 507 503 // Like placeCustomFortress just it takes type (a fortress type string, has to be in fortressTypes) instead of an instance of Fortress 508 504 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 509 function placeFortress(centerX, centerY, type , style, playerId, orientation)505 function placeFortress(centerX, centerY, type="medium", style, playerId=0, orientation=0) 510 506 { 511 507 // Graciously handle arguments 512 type = (type || "medium"); 513 playerId = (playerId || 0); 514 if (!wallStyles.hasOwnProperty(style)) 515 { 516 if (playerId == 0) 517 style = (style || "palisades"); 518 else 519 style = (getCivCode(playerId-1)); 520 } 521 orientation = (orientation || 0); 508 if (!style || !g_WallStyles[style]) 509 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 522 510 523 511 // Call placeCustomFortress with the given arguments 524 placeCustomFortress(centerX, centerY, fortressTypes[type], style, playerId, orientation);512 placeCustomFortress(centerX, centerY, g_FortressTypes[type], style, playerId, orientation); 525 513 } 526 514 527 515 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … function placeFortress(centerX, centerY, type, style, playerId, orientation) 538 526 // 539 527 // TODO: Maybe add angle offset for more generic looking? 540 528 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 541 function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, playerId , endWithFirst)529 function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, playerId=0, endWithFirst=true) 542 530 { 543 531 // Setup optional arguments to the default 544 wallPart = (wallPart || ["tower", "wallLong"]); 545 playerId = (playerId || 0); 546 if (!wallStyles.hasOwnProperty(style)) 547 { 548 if (playerId == 0) 549 style = (style || "palisades"); 550 else 551 style = (getCivCode(playerId-1)); 552 } 553 endWithFirst = typeof endWithFirst == "undefined" ? true : endWithFirst; 532 wallPart = wallPart || ["tower", "long"]; 533 if (!style || !g_WallStyles[style]) 534 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 554 535 555 536 // Check arguments 556 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 557 { 558 var bending = wallStyles[style][wallPart[elementIndex]].bending; 559 if (bending != 0) 560 warn("Bending is not supported by placeLinearWall but a bending wall element is used: " + wallPart[elementIndex] + " -> wallStyles[style][wallPart[elementIndex]].entPath"); 561 } 537 for (let element of wallPart) 538 if (getWallElement(style, element).bend != 0) 539 warn("Bending is not supported by placeLinearWall but the following bending wall element was used: " + element); 540 562 541 // Setup number of wall parts 563 542 var totalLength = getDistance(startX, startY, targetX, targetY); 564 var wallPartLength = 0; 565 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 566 wallPartLength += wallStyles[style][wallPart[elementIndex]].width; 543 var wallPartLength = getWallLength(style, wallPart); 567 544 var numParts = 0; 568 545 if (endWithFirst == true) 569 numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength);546 numParts = ceil((totalLength - getWallElement(style, wallPart[0]).length) / wallPartLength); 570 547 else 571 548 numParts = ceil(totalLength / wallPartLength); 549 572 550 // Setup scale factor 573 551 var scaleFactor = 1; 574 552 if (endWithFirst == true) 575 scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);553 scaleFactor = totalLength / (numParts * wallPartLength + getWallElement(style, wallPart[0]).length); 576 554 else 577 555 scaleFactor = totalLength / (numParts * wallPartLength); 556 578 557 // Setup angle 579 558 var wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed... 580 559 var placeAngle = wallAngle - PI/2; … … function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, play 585 564 { 586 565 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 587 566 { 588 var wallEle = wallStyles[style][wallPart[elementIndex]]; 589 // Width correction 590 x += scaleFactor * wallEle.width/2 * cos(wallAngle); 591 y += scaleFactor * wallEle.width/2 * sin(wallAngle); 567 let wallEle = getWallElement(style, wallPart[elementIndex]); 568 let wallLength = (wallEle.length - getOverlap(style)) / 2; 569 let distX = scaleFactor * wallLength * cos(wallAngle); 570 let distY = scaleFactor * wallLength * sin(wallAngle); 571 // Length correction 572 x += distX; 573 y += distY; 592 574 // Indent correction 593 varplaceX = x - wallEle.indent * sin(wallAngle);594 varplaceY = y + wallEle.indent * cos(wallAngle);575 let placeX = x - wallEle.indent * sin(wallAngle); 576 let placeY = y + wallEle.indent * cos(wallAngle); 595 577 // Placement 596 varentPath = wallEle.entPath;578 let entPath = wallEle.entPath; 597 579 if (entPath !== undefined) 598 580 placeObject(placeX, placeY, entPath, playerId, placeAngle + wallEle.angle); 599 x += scaleFactor * wallEle.width/2 * cos(wallAngle); 600 y += scaleFactor * wallEle.width/2 * sin(wallAngle); 581 // Prep for next object 582 x += distX; 583 y += distY; 601 584 } 602 585 } 603 586 if (endWithFirst == true) 604 587 { 605 var wallEle = wallStyles[style][wallPart[0]]; 606 x += scaleFactor * wallEle.width/2 * cos(wallAngle); 607 y += scaleFactor * wallEle.width/2 * sin(wallAngle); 588 var wallEle = getWallElement(style, wallPart[0]); 589 let wallLength = (wallEle.length - getOverlap(style)) / 2; 590 x += scaleFactor * wallLength * cos(wallAngle); 591 y += scaleFactor * wallLength * sin(wallAngle); 608 592 var entPath = wallEle.entPath; 609 593 if (entPath !== undefined) 610 594 placeObject(x, y, entPath, playerId, placeAngle + wallEle.angle); … … function placeLinearWall(startX, startY, targetX, targetY, wallPart, style, play 633 617 // TODO: Check if maxBendOff parameter works in all cases 634 618 // TODO: Perhaps add functionality for spirals 635 619 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 636 function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId , orientation, maxAngle, endWithFirst, maxBendOff)620 function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId=0, orientation=0, maxAngle=TWO_PI, endWithFirst, maxBendOff=0) 637 621 { 638 622 // Setup optional arguments to the default 639 wallPart = (wallPart || ["tower", "wallLong"]); 640 playerId = (playerId || 0); 641 if (!wallStyles.hasOwnProperty(style)) 642 { 643 if (playerId == 0) 644 style = (style || "palisades"); 645 else 646 style = (getCivCode(playerId-1)); 647 } 648 orientation = (orientation || 0); 649 maxAngle = (maxAngle || 2*PI); 623 wallPart = wallPart || ["tower", "long"]; 624 if (!style || !g_WallStyles[style]) 625 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 650 626 if (endWithFirst === undefined) 651 627 { 652 if (maxAngle >= 2*PI - 0.001) // Can this be done better?628 if (maxAngle >= TWO_PI - 0.001) // Can this be done better? 653 629 endWithFirst = false; 654 630 else 655 631 endWithFirst = true; 656 632 } 657 maxBendOff = (maxBendOff || 0);658 633 659 634 // Check arguments 660 635 if (maxBendOff > PI/2 || maxBendOff < 0) 661 636 warn("placeCircularWall maxBendOff should satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff); 662 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 663 { 664 var bending = wallStyles[style][wallPart[elementIndex]].bending; 665 if (bending != 0) 666 warn("Bending is not supported by placeCircularWall but a bending wall element is used: " + wallPart[elementIndex]); 667 } 637 for (let element of wallPart) 638 if (getWallElement(style, element).bend != 0) 639 warn("Bending is not supported by placeCircularWall but the following bending wall element was used: " + element); 640 668 641 // Setup number of wall parts 669 642 var totalLength = maxAngle * radius; 670 var wallPartLength = 0; 671 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++) 672 wallPartLength += wallStyles[style][wallPart[elementIndex]].width; 643 var wallPartLength = getWallLength(style, wallPart); 673 644 var numParts = 0; 674 645 if (endWithFirst == true) 675 646 { 676 numParts = ceil((totalLength - wallStyles[style][wallPart[0]].width) / wallPartLength);647 numParts = ceil((totalLength - getWallElement(style, wallPart[0]).length) / wallPartLength); 677 648 } 678 649 else 679 650 { … … function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, 682 653 // Setup scale factor 683 654 var scaleFactor = 1; 684 655 if (endWithFirst == true) 685 scaleFactor = totalLength / (numParts * wallPartLength + wallStyles[style][wallPart[0]].width);656 scaleFactor = totalLength / (numParts * wallPartLength + getWallElement(style, wallPart[0]).length); 686 657 else 687 658 scaleFactor = totalLength / (numParts * wallPartLength); 688 659 // Place wall entities 689 660 var actualAngle = orientation + (2*PI - maxAngle) / 2; 690 661 var x = centerX + radius*cos(actualAngle); 691 662 var y = centerY + radius*sin(actualAngle); 692 for ( varpartIndex = 0; partIndex < numParts; partIndex++)663 for (let partIndex = 0; partIndex < numParts; partIndex++) 693 664 { 694 for ( var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)665 for (let wallEle of wallPart) 695 666 { 696 var wallEle = wallStyles[style][wallPart[elementIndex]];667 wallEle = getWallElement(style, wallEle); 697 668 // Width correction 698 var addAngle = scaleFactor * wallEle.width/ radius;699 vartargetX = centerX + radius * cos(actualAngle + addAngle);700 vartargetY = centerY + radius * sin(actualAngle + addAngle);701 varplaceX = x + (targetX - x)/2;702 varplaceY = y + (targetY - y)/2;703 varplaceAngle = actualAngle + addAngle/2;669 let addAngle = scaleFactor * (wallEle.length - getOverlap(style)) / radius; 670 let targetX = centerX + radius * cos(actualAngle + addAngle); 671 let targetY = centerY + radius * sin(actualAngle + addAngle); 672 let placeX = x + (targetX - x)/2; 673 let placeY = y + (targetY - y)/2; 674 let placeAngle = actualAngle + addAngle/2; 704 675 // Indent correction 705 676 placeX -= wallEle.indent * cos(placeAngle); 706 677 placeY -= wallEle.indent * sin(placeAngle); … … function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, 716 687 } 717 688 if (endWithFirst == true) 718 689 { 719 var wallEle = wallStyles[style][wallPart[0]];720 var addAngle = scaleFactor * wallEle. width / radius;690 var wallEle = getWallElement(style, wallPart[0]); 691 var addAngle = scaleFactor * wallEle.length / radius; 721 692 var targetX = centerX + radius * cos(actualAngle + addAngle); 722 693 var targetY = centerY + radius * sin(actualAngle + addAngle); 723 694 var placeX = x + (targetX - x)/2; … … function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, 747 718 // TODO: Check some arguments 748 719 // TODO: Add eccentricity and perhaps make it just call placeIrregularPolygonalWall with irregularity = 0 749 720 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 750 function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement, style, playerId , orientation, numCorners, skipFirstWall)721 function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement, style, playerId=0, orientation=0, numCorners=8, skipFirstWall=true) 751 722 { 752 723 // Setup optional arguments to the default 753 wallPart = (wallPart || ["wallLong", "tower"]); 754 cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well... 755 playerId = (playerId || 0); 756 if (!wallStyles.hasOwnProperty(style)) 757 { 758 if (playerId == 0) 759 style = (style || "palisades"); 760 else 761 style = (getCivCode(playerId-1)); 762 } 763 orientation = (orientation || 0); 764 numCorners = (numCorners || 8); 765 skipFirstWall = (skipFirstWall || true); 766 724 wallPart = wallPart || ["long", "tower"]; 725 cornerWallElement = cornerWallElement || "tower"; // Don't use wide elements for this. Not supported well... 726 if (!style || !g_WallStyles[style]) 727 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 728 767 729 // Setup angles 768 var angleAdd = 2*PI/numCorners;730 var angleAdd = TWO_PI/numCorners; 769 731 var angleStart = orientation - angleAdd/2; 732 770 733 // Setup corners 771 734 var corners = []; 772 for ( vari = 0; i < numCorners; i++)735 for (let i = 0; i < numCorners; i++) 773 736 corners.push([centerX + radius*cos(angleStart + i*angleAdd), centerY + radius*sin(angleStart + i*angleAdd)]); 737 774 738 // Place Corners and walls 775 for ( vari = 0; i < numCorners; i++)739 for (let i = 0; i < numCorners; i++) 776 740 { 777 varangleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY);778 placeObject(corners[i][0], corners[i][1], wallStyles[style][cornerWallElement].entPath, playerId, angleToCorner);741 let angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY); 742 placeObject(corners[i][0], corners[i][1], getWallElement(style, cornerWallElement).entPath, playerId, angleToCorner); 779 743 if (!(skipFirstWall && i == 0)) 780 744 { 745 let cornerLength = getWallElement(style, cornerWallElement).length / 2; 746 let cornerAngle = angleToCorner + angleAdd / 2; 747 let cornerX = cornerLength * sin(cornerAngle); 748 let cornerY = cornerLength * cos(cornerAngle); 781 749 placeLinearWall( 782 750 // Adjustment to the corner element width (approximately) 783 corners[i][0] + wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAdd/2), // startX784 corners[i][1] - wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAdd/2), // startY785 corners[(i+1)%numCorners][0] - wallStyles[style][cornerWallElement].width/2 * sin(angleToCorner + angleAdd/2), // targetX786 corners[(i+1)%numCorners][1] + wallStyles[style][cornerWallElement].width/2 * cos(angleToCorner + angleAdd/2), // targetY751 corners[i][0] + cornerX, // startX 752 corners[i][1] - cornerY, // startY 753 corners[(i+1)%numCorners][0] - cornerX, // targetX 754 corners[(i+1)%numCorners][1] + cornerY, // targetY 787 755 wallPart, style, playerId); 788 756 } 789 757 } … … function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen 800 768 // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia 801 769 // playerId Optional. Integer number of the player. Default is 0 (gaia) 802 770 // orientation Optional. Angle from the center to the first linear wall part placed. Default is 0 (towards positive X/right) 803 // numCorners Optional. How many corners the polygon will have. Default is 8 (matching a civ centers territory)771 // numCorners Optional. How many corners the polygon will have. Default is randomly chosen from 'tween 5 & 7 inclusive 804 772 // irregularity Optional. How irregular the polygon will be. 0 means regular, 1 means VERY irregular. Default is 0.5 805 // skipFirstWall Optional. Boolean. If the first linear wall part will be left opened as entrance. Default is true773 // skipFirstWall Optional. Boolean. If the first linear wall part will be left opened as entrance. Default is false 806 774 // wallPartsAssortment Optional. An array of wall part arrays to choose from for each linear wall connecting the corners. Default is hard to describe ^^ 807 775 // 808 776 // NOTE: wallPartsAssortment is put to the end because it's hardest to set … … function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen 811 779 // TODO: Check some arguments 812 780 // TODO: Perhaps add eccentricity 813 781 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 814 function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement , style, playerId, orientation, numCorners, irregularity, skipFirstWall, wallPartsAssortment)782 function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement="tower", style, playerId=0, orientation=0, numCorners, irregularity=0.5, skipFirstWall=false, wallPartsAssortment) 815 783 { 816 784 // Setup optional arguments 817 playerId = (playerId || 0); 818 if (!wallStyles.hasOwnProperty(style)) 819 { 820 if (playerId == 0) 821 style = (style || "palisades"); 822 else 823 style = (getCivCode(playerId-1)); 824 } 825 785 if (!style || !g_WallStyles[style]) 786 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 787 numCorners = (numCorners || randInt(5, 7)); 788 826 789 // Generating a generic wall part assortment with each wall part including 1 gate lengthened by walls and towers 827 790 // NOTE: It might be a good idea to write an own function for that... 828 var defaultWallPartsAssortment = [[" wallShort"], ["wall"], ["wallLong"], ["gate", "tower", "wallShort"]];791 var defaultWallPartsAssortment = [["short"], ["medium"], ["long"], ["gate", "tower", "short"]]; 829 792 var centeredWallPart = ["gate"]; 830 var extandingWallPartAssortment = [["tower", " wallLong"], ["tower", "wall"]];793 var extandingWallPartAssortment = [["tower", "long"], ["tower", "medium"]]; 831 794 defaultWallPartsAssortment.push(centeredWallPart); 832 795 for (var i = 0; i < extandingWallPartAssortment.length; i++) 833 796 { … … function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement 847 810 } 848 811 // Setup optional arguments to the default 849 812 wallPartsAssortment = (wallPartsAssortment || defaultWallPartsAssortment); 850 cornerWallElement = (cornerWallElement || "tower"); // Don't use wide elements for this. Not supported well... 851 style = (style || "palisades"); 852 playerId = (playerId || 0); 853 orientation = (orientation || 0); 854 numCorners = (numCorners || randInt(5, 7)); 855 irregularity = (irregularity || 0.5); 856 skipFirstWall = (skipFirstWall || false); 813 857 814 // Setup angles 858 var angleToCover = 2*PI;815 var angleToCover = TWO_PI; 859 816 var angleAddList = []; 860 817 for (var i = 0; i < numCorners; i++) 861 818 { … … function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement 875 832 // Setup best wall parts for the different walls (a bit confusing naming...) 876 833 var wallPartLengths = []; 877 834 var maxWallPartLength = 0; 878 for ( var partIndex = 0; partIndex < wallPartsAssortment.length; partIndex++)835 for (let wallPart of wallPartsAssortment) 879 836 { 880 var length = wallPartLengths[partIndex];881 wallPartLengths.push( getWallLength(wallPartsAssortment[partIndex], style));837 var length = getWallLength(style, wallPart); 838 wallPartLengths.push(length); 882 839 if (length > maxWallPartLength) 883 840 maxWallPartLength = length; 884 841 } 842 885 843 var wallPartList = []; // This is the list of the wall parts to use for the walls between the corners, not to confuse with wallPartsAssortment! 886 844 for (var i = 0; i < numCorners; i++) 887 845 { 888 var bestWallPart = []; // This is a simp elwall part not a wallPartsAssortment!889 var bestWallLength = 99999999;846 var bestWallPart = []; // This is a simple wall part not a wallPartsAssortment! 847 var bestWallLength = Number.MAX_VALUE; 890 848 // NOTE: This is not exactly like the length the wall will be in the end. Has to be tweaked... 891 849 var wallLength = getDistance(corners[i][0], corners[i][1], corners[(i+1)%numCorners][0], corners[(i+1)%numCorners][1]); 892 850 var numWallParts = ceil(wallLength/maxWallPartLength); … … function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement 901 859 } 902 860 wallPartList.push(bestWallPart); 903 861 } 862 904 863 // Place Corners and walls 905 864 for (var i = 0; i < numCorners; i++) 906 865 { 907 866 var angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY); 908 placeObject(corners[i][0], corners[i][1], wallStyles[style][cornerWallElement].entPath, playerId, angleToCorner);867 placeObject(corners[i][0], corners[i][1], getWallElement(style, cornerWallElement).entPath, playerId, angleToCorner); 909 868 if (!(skipFirstWall && i == 0)) 910 869 { 870 let cornerLength = getWallElement(style, cornerWallElement).length / 2; 911 871 placeLinearWall( 912 872 // Adjustment to the corner element width (approximately) 913 corners[i][0] + wallStyles[style][cornerWallElement].width/2* sin(angleToCorner + angleAddList[i]/2), // startX914 corners[i][1] - wallStyles[style][cornerWallElement].width/2* cos(angleToCorner + angleAddList[i]/2), // startY915 corners[(i+1)%numCorners][0] - wallStyles[style][cornerWallElement].width/2* sin(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetX916 corners[(i+1)%numCorners][1] + wallStyles[style][cornerWallElement].width/2* cos(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetY873 corners[i][0] + cornerLength * sin(angleToCorner + angleAddList[i]/2), // startX 874 corners[i][1] - cornerLength * cos(angleToCorner + angleAddList[i]/2), // startY 875 corners[(i+1)%numCorners][0] - cornerLength * sin(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetX 876 corners[(i+1)%numCorners][1] + cornerLength * cos(angleToCorner + angleAddList[(i+1)%numCorners]/2), // targetY 917 877 wallPartList[i], style, playerId, false); 918 878 } 919 879 } … … function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement 926 886 // This is the default Iberian civ bonus starting wall 927 887 // 928 888 // centerX/Y The approximate center coordinates of the fortress 929 // radius The approximate radius of the wall to be placed889 // radius Optional. The approximate radius of the wall to be placed. Default is 20 930 890 // playerId Optional. Integer number of the player. Default is 0 (gaia) 931 891 // style Optional. Wall style string. Default is the civ of the given player, "palisades" for gaia 932 // irregularity Optional. Float between 0 (circle) and 1 (very spiky), default is 1/2892 // irregularity Optional. Float between 0 (circle) and 1 (very spiky), default is 0.5 933 893 // gateOccurence Optional. Integer number, every n-th walls will be a gate instead. Default is 3 934 894 // maxTrys Optional. How often the function tries to find a better fitting shape at max. Default is 100 935 895 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 936 function placeGenericFortress(centerX, centerY, radius , playerId, style, irregularity, gateOccurence, maxTrys)896 function placeGenericFortress(centerX, centerY, radius=20, playerId=0, style, irregularity=0.5, gateOccurence=3, maxTrys=100) 937 897 { 938 898 // Setup optional arguments 939 radius = (radius || 20); 940 playerId = (playerId || 0); 941 if (!wallStyles.hasOwnProperty(style)) 942 { 943 if (playerId == 0) 944 style = (style || "palisades"); 945 else 946 style = (getCivCode(playerId-1)); 947 } 948 irregularity = (irregularity || 1/2); 949 gateOccurence = (gateOccurence || 3); 950 maxTrys = (maxTrys || 100); 899 if (!style || !g_WallStyles[style]) 900 style = (playerId == 0) ? "palisade" : getCivCode(playerId-1)+"_stone"; 951 901 952 902 // Setup some vars 953 903 var startAngle = randFloat(0, 2*PI); 954 904 var actualOffX = radius*cos(startAngle); 955 905 var actualOffY = radius*sin(startAngle); 956 906 var actualAngle = startAngle; 957 var pointDistance = wallStyles[style]["wallLong"].width + wallStyles[style]["tower"].width;907 var pointDistance = getWallLength(style, ["long", "tower"]); 958 908 // Searching for a well fitting point derivation 959 909 var tries = 0; 960 910 var bestPointDerivation = undefined; 961 911 var minOverlap = 1000; 962 912 var overlap = undefined; 963 while (tries < maxTrys && minOverlap > wallStyles[style]["tower"].width / 10)913 while (tries < maxTrys && minOverlap > getOverlap(style)) 964 914 { 965 915 var pointDerivation = []; 966 916 var distanceToTarget = 1000; … … function placeGenericFortress(centerX, centerY, radius, playerId, style, irregul 969 919 { 970 920 var indent = randFloat(-irregularity*pointDistance, irregularity*pointDistance); 971 921 var tmpAngle = getAngle(actualOffX, actualOffY, 972 (radius + indent)*cos(actualAngle + (pointDistance / radius)),973 (radius + indent)*sin(actualAngle + (pointDistance / radius)));922 (radius + indent)*cos(actualAngle + pointDistance / radius), 923 (radius + indent)*sin(actualAngle + pointDistance / radius)); 974 924 actualOffX += pointDistance*cos(tmpAngle); 975 925 actualOffY += pointDistance*sin(tmpAngle); 976 926 actualAngle = getAngle(0, 0, actualOffX, actualOffY); … … function placeGenericFortress(centerX, centerY, radius, playerId, style, irregul 999 949 var targetX = centerX + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][0]; 1000 950 var targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1]; 1001 951 var angle = getAngle(startX, startY, targetX, targetY); 1002 var wallElement = " wallLong";952 var wallElement = "long"; 1003 953 if ((pointIndex + 1) % gateOccurence == 0) 1004 954 wallElement = "gate"; 1005 var entPath = wallStyles[style][wallElement].entPath; 955 956 var entPath = getWallElement(style, wallElement).entPath; 1006 957 if (entPath) 1007 958 { 1008 959 placeObject(startX + (getDistance(startX, startY, targetX, targetY)/2)*cos(angle), // placeX 1009 960 startY + (getDistance(startX, startY, targetX, targetY)/2)*sin(angle), // placeY 1010 entPath, playerId, angle - PI/2 + wallStyles[style][wallElement].angle);961 entPath, playerId, angle - PI/2 + getWallElement(style, wallElement).angle); 1011 962 } 1012 963 // Place tower 1013 964 var startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0]; 1014 965 var startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1]; 1015 966 var angle = getAngle(startX, startY, targetX, targetY); 1016 placeObject(centerX + bestPointDerivation[pointIndex][0], centerY + bestPointDerivation[pointIndex][1], wallStyles[style]["tower"].entPath, playerId, angle - PI/2 + wallStyles[style]["tower"].angle); 967 968 var tower = getWallElement(style, "tower"); 969 placeObject(centerX + bestPointDerivation[pointIndex][0], centerY + bestPointDerivation[pointIndex][1], tower.entPath, playerId, angle - PI/2 + tower.angle); 1017 970 } 1018 971 } -
binaries/data/mods/public/maps/random/wall_demo.js
const distToOtherWalls = 10; 61 61 var buildableMapSize = mapSize - 2 * distToMapBorder; 62 62 var actualX = distToMapBorder; 63 63 var actualY = distToMapBorder; 64 // Wall styles are chosen by strings so the civ strings got by getCivCode() can be used 65 var wallStyleList = getCivList(); 66 // Other styles may be available as well... 67 wallStyleList.push("rome_siege"); 68 wallStyleList.push("palisades"); 69 // Check if all wall styles are present and remove unknown ones 70 for (var i = 0; i < wallStyleList.length; i++) 71 if (!wallStyles.hasOwnProperty(wallStyleList[i])) 72 wallStyleList.splice(i, 1); 73 64 var wallStyleList = g_WallStyleList; 74 65 75 66 //////////////////////////////////////// 76 67 // Custom wall placement (element based) 77 68 //////////////////////////////////////// 78 var wall = [' endLeft', 'wallLong', 'tower', 'tower', 'tower', 'wall', 'outpost', 'wall', 'cornerOut', 'wall', 'cornerIn', 'wall', 'house', 'endRight', 'entryTower', 'endLeft', 'wallShort', 'barracks', 'gate', 'tower', 'wall', 'endRight'];69 var wall = ['start', 'long', 'tower', 'medium', 'outpost', 'medium', 'cornerOut', 'medium', 'cornerIn', 'medium', 'house', 'end', 'entryTower', 'start', 'short', 'barracks', 'gate', 'tower', 'medium', 'fort', 'medium', 'end']; 79 70 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 80 71 { 81 72 var startX = actualX + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the first wall element … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 84 75 var orientation = PI/16 * sin(styleIndex * PI/4); // Orientation of the first wall element. 0 means 'outside' or 'front' is right (positive X, like object placement in Atlas) 85 76 // That means the wall will be build towards top (positive Y) if no corners are used 86 77 var playerId = 0; // Owner of the wall (like in placeObject). 0 is Gaia, 1 is Player 1 (default color blue), ... 87 placeWall(startX, startY, wall, style, playerId, orientation); // Actually plac ingthe wall78 placeWall(startX, startY, wall, style, playerId, orientation); // Actually place the wall 88 79 } 89 80 actualX = distToMapBorder; // Reset actualX 90 81 actualY += 80 + distToOtherWalls; // Increase actualY for next wall placement method 91 82 83 92 84 ////////////////////////////////////////////////////////////// 93 85 // Default fortress placement (chosen by fortress type string) 94 86 ////////////////////////////////////////////////////////////// … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 105 97 placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the fortress 106 98 } 107 99 actualX = distToMapBorder; // Reset actualX 108 actualY += 2 * fortressRadius + 2 * distToOtherWalls; // Increase actualY for next wall placement method 100 actualY += 2 * fortressRadius + distToOtherWalls; // Increase actualY for next wall placement method 101 102 ////////////////////////////////////////////////////////////// 103 // 'generic' fortress placement (iberian wall circuit code) 104 ////////////////////////////////////////////////////////////// 105 var radius = min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall circle 106 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 107 { 108 var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the fortress 109 var centerY = actualY + radius; // Y coordinate of the center of the fortress 110 var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades' 111 var playerId = 0; // Owner of the wall. 0 is Gaia, 1 is Player 1 (default color blue), ... 112 placeGenericFortress(centerX, centerY, radius, playerId, style); // Actually place the fortress 113 placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the fortress 114 } 115 actualX = distToMapBorder; // Reset actualX 116 actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method 109 117 110 118 ////////////////////////// 111 119 // Circular wall placement … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 118 126 { 119 127 var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle 120 128 var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ... 121 var wallPart = ['tower', ' wall', 'house']; // List of wall elements the wall will be build of. Optional, default id ['wall']129 var wallPart = ['tower', 'medium', 'house']; // List of wall elements the wall will be build of. Optional, default id ['wall'] 122 130 var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades' 123 131 var maxAngle = PI/2 * (styleIndex%3 + 2); // How far the wall should circumvent the center 124 132 placeCircularWall(centerX, centerY, radius, wallPart, style, playerId, orientation, maxAngle); // Actually placing the wall … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 128 136 actualX = distToMapBorder; // Reset actualX 129 137 actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method 130 138 131 /////////////////////////// 132 // Polygonal wall placement133 /////////////////////////// 139 /////////////////////////////////// 140 // Regular Polygonal wall placement 141 /////////////////////////////////// 134 142 // NOTE: Don't use bending wall elements like corners here! 135 143 var radius = min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons 136 144 var centerY = actualY + radius; // Y coordinate of the center of the wall polygon … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 140 148 var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle 141 149 var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ... 142 150 var cornerWallElement = 'tower'; // With wall element type will be uset for the corners of the polygon 143 var wallPart = [' wall', 'tower']; // List of wall elements the wall will be build of. Optional, default id ['wall']151 var wallPart = ['medium', 'tower']; // List of wall elements the wall will be build of. Optional, default id ['wall'] 144 152 var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades' 145 153 var numCorners = (styleIndex)%6 + 3; // How many corners the plogon will have 146 154 var skipFirstWall = true; // If the wall should be open towards orientation … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 151 159 actualX = distToMapBorder; // Reset actualX 152 160 actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method 153 161 162 ///////////////////////////////////// 163 // Irregular Polygonal wall placement 164 ///////////////////////////////////// 165 // NOTE: Don't use bending wall elements like corners here! 166 var radius = min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons 167 var centerY = actualY + radius; // Y coordinate of the center of the wall polygon 168 var orientation = 0; // Where the wall circle will be open if ???, see below. Otherwise where the first wall will be placed 169 for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 170 { 171 var centerX = actualX + radius + styleIndex * buildableMapSize/wallStyleList.length; // X coordinate of the center of the wall circle 172 var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ... 173 var cornerWallElement = 'tower'; // With wall element type will be uset for the corners of the polygon 174 var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades' 175 var numCorners = (styleIndex)%6 + 3; // How many corners the plogon will have 176 var skipFirstWall = true; // If the wall should be open towards orientation 177 placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerId, orientation, numCorners, undefined, skipFirstWall); 178 placeObject(centerX, centerY, 'other/obelisk', 0, 0*PI); // Place visual marker to see the center of the wall circle 179 orientation += PI/16; // Increasing orientation to see how rotation works (like for object placement) 180 } 181 actualX = distToMapBorder; // Reset actualX 182 actualY += 2 * radius + distToOtherWalls; // Increase actualY for next wall placement method 183 184 154 185 //////////////////////// 155 186 // Linear wall placement 156 187 //////////////////////// … … for (var styleIndex = 0; styleIndex < wallStyleList.length; styleIndex++) 166 197 var endX = startX; // X coordinate the wall will end 167 198 var endY = actualY + (wallIndex + 1) * maxWallLength/numWallsPerStyle; // Y coordinate the wall will end 168 199 var playerId = 0; // Player ID of the player owning the wall, 0 is Gaia, 1 is the first player (default blue), ... 169 var wallPart = ['tower', ' wall']; // List of wall elements the wall will be build of200 var wallPart = ['tower', 'medium']; // List of wall elements the wall will be build of 170 201 var style = wallStyleList[styleIndex]; // The wall's style like 'cart', 'iber', 'pers', 'rome', 'romeSiege' or 'palisades' 171 202 placeLinearWall(startX, startY, endX, endY, wallPart, style, playerId); // Actually placing the wall 172 203 // placeObject(startX, startY, 'other/obelisk', 0, 0*PI); // Place visual marker to see where exsactly the wall begins -
binaries/data/mods/public/maps/random/wall_demo.json
7 7 "BaseHeight" : 0, 8 8 "Keywords": ["demo"], 9 9 "CircularMap" : false, 10 "RevealMap": true, 10 11 "XXXXXX" : "Optionally define other things here, like we would for a scenario" 11 12 } 12 13 } 14 No newline at end of file -
binaries/data/mods/public/simulation/components/WallPiece.js
WallPiece.prototype.Schema = 6 6 "</a:example>" + 7 7 "<element name='Length'>" + 8 8 "<ref name='nonNegativeDecimal'/>" + 9 "</element>"; 9 "</element>" + 10 "<optional>" + 11 "<element name='Orientation'>" + 12 "<ref name='nonNegativeDecimal'/>" + 13 "</element>" + 14 "</optional>" + 15 "<optional>" + 16 "<element name='Indent'>" + 17 "<data type='decimal'/>" + 18 "</element>" + 19 "</optional>" + 20 "<optional>" + 21 "<element name='Bend'>" + 22 "<data type='decimal'/>" + 23 "</element>" + 24 "</optional>"; 10 25 11 26 12 27 WallPiece.prototype.Init = function() -
binaries/data/mods/public/simulation/components/WallSet.js
WallSet.prototype.Schema = 21 21 "<element name='WallShort' a:help='Template name of the short wall segment'>" + 22 22 "<text/>" + 23 23 "</element>" + 24 "<optional>" + 25 "<element name='WallCurveQuarter'>" + 26 "<text/>" + 27 "</element>" + 28 "</optional>" + 29 "<optional>" + 30 "<element name='WallCurveEighth'>" + 31 "<text/>" + 32 "</element>" + 33 "</optional>" + 34 "<optional>" + 35 "<element name='WallEnd'>" + 36 "<text/>" + 37 "</element>" + 38 "</optional>" + 39 "<optional>" + 40 "<element name='Fort'>" + 41 "<text/>" + 42 "</element>" + 43 "</optional>" + 24 44 "</interleave>" + 25 45 "</element>" + 26 46 "<element name='MinTowerOverlap' a:help='Maximum fraction that wall segments are allowed to overlap towers, where 0 signifies no overlap and 1 full overlap'>" + -
binaries/data/mods/public/simulation/data/civs/athen.json
110 110 } 111 111 ], 112 112 "WallSets": 113 { 114 "Palisades": 115 { 116 "Template": "other/wallset_palisade", 117 "Scale": 0.55 118 }, 119 "Stone": 120 { 121 "Template": "structures/athen_wallset_stone", 122 "Scale": 1.5 123 } 124 }, 113 [ 114 "other/wallset_palisade", 115 "structures/athen_wallset_stone" 116 ], 125 117 "StartEntities": 126 118 [ 127 119 { -
binaries/data/mods/public/simulation/data/civs/brit.json
88 88 } 89 89 ], 90 90 "WallSets": 91 { 92 "Palisades": 93 { 94 "Template": "other/wallset_palisade", 95 "Scale": 0.55 96 }, 97 "Stone": 98 { 99 "Template": "structures/athen_wallset_stone", 100 "Scale": 1.5 101 } 102 }, 91 [ 92 "other/wallset_palisade", 93 "structures/brit_wallset_stone" 94 ], 103 95 "StartEntities": 104 96 [ 105 97 { -
binaries/data/mods/public/simulation/data/civs/cart.json
113 113 } 114 114 ], 115 115 "WallSets": 116 { 117 "Palisades": 118 { 119 "Template": "other/wallset_palisade", 120 "Scale": 0.55 121 }, 122 "Stone": 123 { 124 "Template": "structures/athen_wallset_stone", 125 "Scale": 1.8 126 } 127 }, 116 [ 117 "other/wallset_palisade", 118 "structures/cart_wallset_stone" 119 ], 128 120 "StartEntities": 129 121 [ 130 122 { -
binaries/data/mods/public/simulation/data/civs/gaul.json
88 88 } 89 89 ], 90 90 "WallSets": 91 { 92 "Palisades": 93 { 94 "Template": "other/wallset_palisade", 95 "Scale": 0.55 96 }, 97 "Stone": 98 { 99 "Template": "structures/athen_wallset_stone", 100 "Scale": 1.5 101 } 102 }, 91 [ 92 "other/wallset_palisade", 93 "structures/gaul_wallset_stone" 94 ], 103 95 "StartEntities": 104 96 [ 105 97 { -
binaries/data/mods/public/simulation/data/civs/iber.json
86 86 } 87 87 ], 88 88 "WallSets": 89 { 90 "Palisades": 91 { 92 "Template": "other/wallset_palisade", 93 "Scale": 0.55 94 }, 95 "Stone": 96 { 97 "Template": "structures/athen_wallset_stone", 98 "Scale": 1.5 99 } 100 }, 89 [ 90 "other/wallset_palisade", 91 "structures/iber_wallset_stone" 92 93 ], 101 94 "StartEntities": 102 95 [ 103 96 { -
binaries/data/mods/public/simulation/data/civs/mace.json
115 115 } 116 116 ], 117 117 "WallSets": 118 { 119 "Palisades": 120 { 121 "Template": "other/wallset_palisade", 122 "Scale": 0.55 123 }, 124 "Stone": 125 { 126 "Template": "structures/athen_wallset_stone", 127 "Scale": 1.5 128 } 129 }, 118 [ 119 "other/wallset_palisade", 120 "structures/mace_wallset_stone" 121 122 ], 130 123 "StartEntities": 131 124 [ 132 125 { -
binaries/data/mods/public/simulation/data/civs/maur.json
95 95 } 96 96 ], 97 97 "WallSets": 98 { 99 "Palisades": 100 { 101 "Template": "other/wallset_palisade", 102 "Scale": 0.55 103 }, 104 "Stone": 105 { 106 "Template": "structures/athen_wallset_stone", 107 "Scale": 1.5 108 } 109 }, 98 [ 99 "other/wallset_palisade", 100 "structures/maur_wallset_stone" 101 102 ], 110 103 "StartEntities": 111 104 [ 112 105 { -
binaries/data/mods/public/simulation/data/civs/pers.json
105 105 } 106 106 ], 107 107 "WallSets": 108 { 109 "Palisades": 110 { 111 "Template": "other/wallset_palisade", 112 "Scale": 0.55 113 }, 114 "Stone": 115 { 116 "Template": "structures/athen_wallset_stone", 117 "Scale": 1.5 118 } 119 }, 108 [ 109 "other/wallset_palisade", 110 "structures/pers_wallset_stone" 111 112 ], 120 113 "StartEntities": 121 114 [ 122 115 { -
binaries/data/mods/public/simulation/data/civs/ptol.json
114 114 } 115 115 ], 116 116 "WallSets": 117 { 118 "Palisades": 119 { 120 "Template": "other/wallset_palisade", 121 "Scale": 0.55 122 }, 123 "Stone": 124 { 125 "Template": "structures/athen_wallset_stone", 126 "Scale": 1.5 127 } 128 }, 117 [ 118 "other/wallset_palisade", 119 "structures/ptol_wallset_stone" 120 121 ], 129 122 "StartEntities": 130 123 [ 131 124 { -
binaries/data/mods/public/simulation/data/civs/rome.json
90 90 } 91 91 ], 92 92 "WallSets": 93 { 94 "Palisades": 95 { 96 "Template": "other/wallset_palisade", 97 "Scale": 0.55 98 }, 99 "Stone": 100 { 101 "Template": "structures/athen_wallset_stone", 102 "Scale": 1.5 103 }, 104 "Siege": 105 { 106 "Template": "structures/rome_wallset_siege", 107 "Scale": 1.5 108 } 109 }, 93 [ 94 "other/wallset_palisade", 95 "structures/rome_wallset_stone", 96 "structures/rome_wallset_siege" 97 98 ], 110 99 "StartEntities": 111 100 [ 112 101 { -
binaries/data/mods/public/simulation/data/civs/sele.json
115 115 } 116 116 ], 117 117 "WallSets": 118 { 119 "Palisades": 120 { 121 "Template": "other/wallset_palisade", 122 "Scale": 0.55 123 }, 124 "Stone": 125 { 126 "Template": "structures/athen_wallset_stone", 127 "Scale": 1.5 128 } 129 }, 118 [ 119 "other/wallset_palisade", 120 "structures/sele_wallset_stone" 121 122 ], 130 123 "StartEntities": 131 124 [ 132 125 { -
binaries/data/mods/public/simulation/data/civs/spart.json
106 106 } 107 107 ], 108 108 "WallSets": 109 { 110 "Palisades": 111 { 112 "Template": "other/wallset_palisade", 113 "Scale": 0.55 114 }, 115 "Stone": 116 { 117 "Template": "structures/athen_wallset_stone", 118 "Scale": 1.5 119 } 120 }, 109 [ 110 "other/wallset_palisade", 111 "structures/spart_wallset_stone" 112 113 ], 121 114 "StartEntities": 122 115 [ 123 116 {