Ticket #1288: wall_builder.js

File wall_builder.js, 28.9 KB (added by FeXoR, 12 years ago)
Line 
1// Functionality to create walls and fortresses
2// Wall object
3function wallElement(type, entity, angle, width, indent, bending)
4{
5 // NOTE: Not all wall elements have a symetry. So there's an direction 'outside' (towards top/positive Z[2 dimensional Y] by default)
6 // In this sense 'right'/'left' means right/left of you when you stand upon the wall and look 'outside'
7 // The wall is build towards 'right' so the next wall element will be placed right of the previous one
8 // In this sense the wall's direction is right meaning the 'bending' of a corner is used for the element following the corner
9 // With 'inside' and 'outside' defined as above, corners bend 'in'/'out' meaning placemant angle is increased/decreased (circlewise like building placement)
10 this.type = type; // Descriptive string for easy to add wall styles. Not really needed (wallTool.wallTypes['type string'] is used). May be helpfull for custom wall elements though.
11 // Wall type documentation:
12 // wall: A blocking straight wall element that mainly lengthens the wall, self-explanatory
13 // tower: A blocking straight wall element with damage potential that slightly lengthens the wall, exsample: wall tower, palisade tower(No attack?)
14 // wallFort: A blocking straight wall element with massive damage potential that lengthens the wall, exsample: fortress, palisade fort
15 // NOTE: Not really needed but for palisades, I don't find it tragic that palisades are much less powerfull
16 // outpost: A zero-length wall element without bending far indented so it stands outside the wall, exsample: outpost, defense tower, watchtower
17 // house: A zero-length wall element without bending far indented so it stands inside the wall, exsample: house, hut, longhouse
18 // gate: A blocking straight wall element with passability determined by owner, example: gate
19 // entry: A non-blocking straight wall element represented by a single indented template, example: defense tower, wall tower, outpost, watchtower, nothing
20 // wideEntry: A non-blocking straight wall element represented by a single indented template, example: fortress? a unit?
21 // NOTE: Not really needed...
22 // endRight: A straight wall element that (only) visually ends the wall to the right (e.g. left of entrys), example: wall tower, palisade ending
23 // endLeft: A straight wall element that (only) visually ends the wall to the left (e.g. right of entrys), example: wall tower, palisade ending
24 // cornerIn: A wall element bending the wall PI/2 (90°) 'inside' (see above), example: wall tower, palisade curve
25 // cornerOut: A wall element bending the wall PI/2 (90°) 'outside' (see above), example: wall tower, palisade curve (placed the other way arround)
26 // barracks: Adding in progress...
27 this.entity = undefined; // Optional. Template (string) that will represent the wall element, example: "other/palisades_rocks_straight"
28 if (entity !== undefined)
29 this.entity = entity;
30 this.angle = 0*PI; // Optional. Placement angle so that 'outside' is 'top' (directs towards positive z, like buildings)
31 if (angle !== undefined)
32 this.angle = angle;
33 this.width = 0; // Optional. The width it lengthens the wall, width because it's the needed space in a right angle to 'outside'
34 if (width !== undefined)
35 this.width = width;
36 this.indent = 0; // Optional. The indentation means its drawn inside (positive values) or pressed outwards (negative values)
37 if (indent !== undefined)
38 this.indent = indent;
39 this.bending = 0*PI; // Optional. How the angle of the wall is changed by this element for the following element, positive is bending 'in'
40 if (bending !== undefined)
41 this.bending = bending;
42};
43
44// Fortress object. A list would do for symetric fortresses but if 'getCenter' don't do sufficient the center can be set manually.
45function fortress(type) // BAD NAME!!! To name a fortress type or a wallTool for a fortress "fortress" might be common!!!
46{
47 this.type = type; // Only usefull to get the type of the actual fortress (by 'wallTool.fortress.type')
48 this.wall = [];
49 this.center = [0, 0]; // X/Z offset (in default orientation) from first wall element to center, perhaps should be the other way around...
50 // NOTE: The 'angle' is not implemented yet!!!
51 this.angle = 0; // Angle the first element has to be placed so that fortress orientation is with main entrance top (default), should always be 0 though.
52};
53
54// The wall tool
55function wallTool(style, fortressType)
56{
57 // General setup
58 this.angle = 0; // Not really needed, may be useful to rotate fortresses after set...
59 this.wallTypes = {}; // An associative array including all wall elements associated with 'wallElement.type'.
60 this.wall = []; // A list of strings (wall element types) for simple wall building
61 this.center = [0, 0] // X/Z offset from first wall element to center, perhaps should be the other way around...
62
63 // Presets needed for wall style
64 this.wallStyles = {};
65 this.style = "palisades"; // Not really needed, perhaps helpfull to check current style
66 if (style !== undefined)
67 this.style = style;
68
69 // Presets needed for tortess types
70 this.fortressTypes = {};
71 this.fortress = false; // Not really needed, perhaps usefull for getting fortress type, should be renamed somehow but simply 'type' is not very descriptive and 'fortressType' may be mistaken as 'fortressTypes'
72 if (fortressType !== undefined)
73 this.fortress = fortressType;
74 this.calculateCenter = true; // If setFortress(Type) shall recalculate the center
75
76 // Adding wall styles
77 // Wall style 'palisades'
78 this.wallStyles["palisades"] = {};
79 // Straight unindented
80 this.wallStyles["palisades"]["wall"] = new wallElement("wall", "other/palisades_rocks_straight", -PI/2, 2.5);
81 this.wallStyles["palisades"]["tower"] = new wallElement("tower", "other/palisades_rocks_tower", -PI/2, 0.7);
82 this.wallStyles["palisades"]["wallFort"] = new wallElement("wallFort", "other/palisades_rocks_fort", PI, 1.7);
83 this.wallStyles["palisades"]["gate"] = new wallElement("gate", "other/palisades_rocks_gate", 0*PI, 3.6);
84 this.wallStyles["palisades"]["endRight"] = new wallElement("endRight", "other/palisades_rocks_end", -PI/2, 0.2);
85 this.wallStyles["palisades"]["endLeft"] = new wallElement("endLeft", "other/palisades_rocks_end", PI/2, 0.2);
86 // Straight indented
87 this.wallStyles["palisades"]["outpost"] = new wallElement("outpost", "other/palisades_rocks_outpost", PI, 0, -2);
88 this.wallStyles["palisades"]["house"] = new wallElement("house", "other/celt_hut", PI, 0, 5);
89 this.wallStyles["palisades"]["barracks"] = new wallElement("barracks", "other/celt_tavern", PI, 0, 5);
90 this.wallStyles["palisades"]["entry"] = new wallElement("entry", "other/palisades_rocks_watchtower", 0*PI, 3.6, -2);
91 this.wallStyles["palisades"]["wideEntry"] = new wallElement("wideEntry", "other/palisades_rocks_fort", PI, 6, 3);
92 // Corners
93 this.wallStyles["palisades"]["cornerIn"] = new wallElement("cornerIn", "other/palisades_rocks_curve", -PI/4, 2.1, 0.7, PI/2);
94 this.wallStyles["palisades"]["cornerOut"] = new wallElement("cornerOut", "other/palisades_rocks_curve", PI/4, 2.1, -0.7, -PI/2);
95 // Wall style 'cart'
96 this.wallStyles["cart"] = {};
97 this.wallStyles["cart"]["wall"] = new wallElement("wall", "structures/cart_wall", 0*PI, 6.2);
98 this.wallStyles["cart"]["tower"] = new wallElement("tower", "structures/cart_wall_tower", PI, 2.7);
99 this.wallStyles["cart"]["wallFort"] = new wallElement("wallFort", "structures/cart_fortress", PI, 5.1, 1.6);
100 this.wallStyles["cart"]["outpost"] = new wallElement("outpost", "structures/cart_outpost", PI, 0, -5);
101 this.wallStyles["cart"]["house"] = new wallElement("house", "structures/cart_house", PI, 0, 7);
102 this.wallStyles["cart"]["gate"] = new wallElement("gate", "structures/cart_wall_gate", 0*PI, 6.2);
103 this.wallStyles["cart"]["entry"] = new wallElement("entry", "structures/cart_defense_tower", PI, 6.2, -5);
104 this.wallStyles["cart"]["wideEntry"] = new wallElement("wideEntry", "structures/cart_fortress", PI, 12, 7);
105 this.wallStyles["cart"]["endRight"] = new wallElement("endRight", "structures/cart_wall_tower", PI, 2.7);
106 this.wallStyles["cart"]["endLeft"] = new wallElement("endLeft", "structures/cart_wall_tower", PI, 2.7);
107 this.wallStyles["cart"]["cornerIn"] = new wallElement("cornerIn", "structures/cart_wall_tower", 5*PI/4, 0.1, 0.9, PI/2);
108 this.wallStyles["cart"]["cornerOut"] = new wallElement("cornerOut", "structures/cart_wall_tower", 3*PI/4, 1.3 /*1.6*/, 0, -PI/2);
109 this.wallStyles["cart"]["barracks"] = new wallElement("barracks", "structures/cart_barracks", PI, 0, 7);
110 // Wall style 'celt'
111 this.wallStyles["celt"] = {};
112 this.wallStyles["celt"]["wall"] = new wallElement("wall", "structures/celt_wall", 0*PI, 5, 0.5);
113 this.wallStyles["celt"]["tower"] = new wallElement("tower", "structures/celt_wall_tower", PI, 0.7);
114 this.wallStyles["celt"]["wallFort"] = new wallElement("wallFort", "structures/celt_fortress_g", PI, 4.2, 2);
115 this.wallStyles["celt"]["outpost"] = new wallElement("outpost", "structures/celt_outpost", PI, 0, -5);
116 this.wallStyles["celt"]["house"] = new wallElement("house", "structures/celt_house", PI, 0, 3);
117 this.wallStyles["celt"]["gate"] = new wallElement("gate", "structures/celt_wall_gate", 0*PI, 3.2);
118 this.wallStyles["celt"]["entry"] = new wallElement("entry", "structures/celt_defense_tower", PI, 6, -5);
119 this.wallStyles["celt"]["wideEntry"] = new wallElement("wideEntry", "structures/celt_fortress_b", PI, 12, 7);
120 this.wallStyles["celt"]["endRight"] = new wallElement("endRight", "structures/celt_wall_tower", PI, 0.7);
121 this.wallStyles["celt"]["endLeft"] = new wallElement("endLeft", "structures/celt_wall_tower", PI, 0.7);
122 this.wallStyles["celt"]["cornerIn"] = new wallElement("cornerIn", "structures/celt_wall_tower", PI, 0.7, 0, PI/2);
123 this.wallStyles["celt"]["cornerOut"] = new wallElement("cornerOut", "structures/celt_wall_tower", PI, 0.7, 0, -PI/2);
124 this.wallStyles["celt"]["barracks"] = new wallElement("barracks", "structures/celt_barracks", PI, 0, 7);
125 // Wall style 'hele'
126 this.wallStyles["hele"] = {};
127 this.wallStyles["hele"]["wall"] = new wallElement("wall", "structures/hele_wall", 0*PI, 5.95);
128 this.wallStyles["hele"]["tower"] = new wallElement("tower", "structures/hele_wall_tower", PI, 1.5);
129 this.wallStyles["hele"]["wallFort"] = new wallElement("wallFort", "structures/hele_fortress", 2*PI/2 /* PI/2 */, 5.1 /* 5.6 */, 1.9 /* 1.9 */);
130 this.wallStyles["hele"]["outpost"] = new wallElement("outpost", "structures/hele_outpost", PI, 0, -5);
131 this.wallStyles["hele"]["house"] = new wallElement("house", "structures/hele_house", PI/2, 0, 6);
132 this.wallStyles["hele"]["gate"] = new wallElement("gate", "structures/hele_wall_gate", 0*PI, 9.1);
133 this.wallStyles["hele"]["entry"] = new wallElement("entry", "structures/hele_defense_tower", PI, 9.1, -4);
134 this.wallStyles["hele"]["wideEntry"] = new wallElement("wideEntry", "structures/hele_fortress", 5*PI/2, 12, 7);
135 this.wallStyles["hele"]["endRight"] = new wallElement("endRight", "structures/hele_wall_tower", PI, 1.5);
136 this.wallStyles["hele"]["endLeft"] = new wallElement("endLeft", "structures/hele_wall_tower", PI, 1.5);
137 this.wallStyles["hele"]["cornerIn"] = new wallElement("cornerIn", "structures/hele_wall_tower", 5*PI/4, 0, 0.5, PI/2);
138 this.wallStyles["hele"]["cornerOut"] = new wallElement("cornerOut", "structures/hele_wall_tower", 3*PI/4, 1, 0, -PI/2);
139 this.wallStyles["hele"]["barracks"] = new wallElement("barracks", "structures/hele_barracks", PI, 0, 6);
140 // Wall style 'iber'
141 this.wallStyles["iber"] = {};
142 this.wallStyles["iber"]["wall"] = new wallElement("wall", "structures/iber_wall", 0*PI, 6.9);
143 this.wallStyles["iber"]["tower"] = new wallElement("tower", "structures/iber_wall_tower", PI, 2.1);
144 this.wallStyles["iber"]["wallFort"] = new wallElement("wallFort", "structures/iber_fortress", PI, 4.5, 0.7);
145 this.wallStyles["iber"]["outpost"] = new wallElement("outpost", "structures/iber_outpost", PI, 0, -5);
146 this.wallStyles["iber"]["house"] = new wallElement("house", "structures/iber_house", PI, 0, 4);
147 this.wallStyles["iber"]["gate"] = new wallElement("gate", "structures/iber_wall_gate", 0*PI, 9.2);
148 this.wallStyles["iber"]["entry"] = new wallElement("entry", "structures/iber_wall_tower", PI, 6.9, -5);
149 this.wallStyles["iber"]["wideEntry"] = new wallElement("wideEntry", "structures/iber_fortress", PI/2, 9.2, 7);
150 this.wallStyles["iber"]["endRight"] = new wallElement("endRight", "structures/iber_wall_tower", PI, 2.1);
151 this.wallStyles["iber"]["endLeft"] = new wallElement("endLeft", "structures/iber_wall_tower", PI, 2.1);
152 this.wallStyles["iber"]["cornerIn"] = new wallElement("cornerIn", "structures/iber_wall_tower", PI, 2.1, 0, PI/2);
153 this.wallStyles["iber"]["cornerIn2"] = new wallElement("cornerIn2", "structures/iber_defense_tower", 5*PI/4, 1, 0.2, PI/2);
154 this.wallStyles["iber"]["cornerIn3"] = new wallElement("cornerIn3", "structures/iber_wall_tower", 5*PI/4, 0.3, 0.5, PI/2);
155 this.wallStyles["iber"]["cornerOut"] = new wallElement("cornerOut", "structures/iber_wall_tower", 3*PI/4, 1.3, 0, -PI/2);
156 this.wallStyles["iber"]["barracks"] = new wallElement("barracks", "structures/iber_barracks", PI, 0, 7);
157 // Wall style 'pers'
158 this.wallStyles["pers"] = {};
159 this.wallStyles["pers"]["wall"] = new wallElement("wall", "structures/pers_wall", 0*PI, 5.9);
160 this.wallStyles["pers"]["tower"] = new wallElement("tower", "structures/pers_wall_tower", PI, 1.7);
161 this.wallStyles["pers"]["wallFort"] = new wallElement("wallFort", "structures/pers_fortress", PI, 5.6/*5.5*/, 1.9/*1.7*/);
162 this.wallStyles["pers"]["outpost"] = new wallElement("outpost", "structures/pers_outpost", PI, 0, -5);
163 this.wallStyles["pers"]["house"] = new wallElement("house", "structures/pers_house", PI, 0, 6);
164 this.wallStyles["pers"]["gate"] = new wallElement("gate", "structures/pers_wall_gate", 0*PI, 6);
165 this.wallStyles["pers"]["entry"] = new wallElement("entry", "structures/pers_defense_tower", PI, 6, -4);
166 this.wallStyles["pers"]["wideEntry"] = new wallElement("wideEntry", "structures/pers_fortress", PI, 12, 7);
167 this.wallStyles["pers"]["endRight"] = new wallElement("endRight", "structures/pers_wall_tower", PI, 1.7);
168 this.wallStyles["pers"]["endLeft"] = new wallElement("endLeft", "structures/pers_wall_tower", PI, 1.7);
169 this.wallStyles["pers"]["cornerIn"] = new wallElement("cornerIn", "structures/pers_wall_tower", 5*PI/4, 0.2, 0.5, PI/2);
170 this.wallStyles["pers"]["cornerOut"] = new wallElement("cornerOut", "structures/pers_wall_tower", 3*PI/4, 0.8, 0, -PI/2);
171 this.wallStyles["pers"]["barracks"] = new wallElement("barracks", "structures/pers_barracks", PI, 0, 7);
172 // Wall style 'rome'
173 this.wallStyles["rome"] = {};
174 this.wallStyles["rome"]["wall"] = new wallElement("wall", "structures/rome_wall", 0*PI, 5.9);
175 this.wallStyles["rome"]["tower"] = new wallElement("tower", "structures/rome_wall_tower", PI, 2.1);
176 this.wallStyles["rome"]["wallFort"] = new wallElement("wallFort", "structures/rome_fortress", PI, 6.3, 2.1);
177 this.wallStyles["rome"]["outpost"] = new wallElement("outpost", "structures/rome_outpost", PI, 0, -5);
178 this.wallStyles["rome"]["house"] = new wallElement("house", "structures/rome_house", PI, 0, 7);
179 this.wallStyles["rome"]["gate"] = new wallElement("gate", "structures/rome_wall_gate", 0*PI, 5.9);
180 this.wallStyles["rome"]["entry"] = new wallElement("entry", "structures/rome_defense_tower", PI, 5.9, -4);
181 this.wallStyles["rome"]["wideEntry"] = new wallElement("wideEntry", "structures/rome_fortress", PI, 12, 7);
182 this.wallStyles["rome"]["endRight"] = new wallElement("endRight", "structures/rome_wall_tower", PI, 2.1);
183 this.wallStyles["rome"]["endLeft"] = new wallElement("endLeft", "structures/rome_wall_tower", PI, 2.1);
184 this.wallStyles["rome"]["cornerIn"] = new wallElement("cornerIn", "structures/rome_wall_tower", 5*PI/4, 0, 0.7, PI/2);
185 this.wallStyles["rome"]["cornerOut"] = new wallElement("cornerOut", "structures/rome_wall_tower", 3*PI/4, 1.1, 0, -PI/2);
186 this.wallStyles["rome"]["barracks"] = new wallElement("barracks", "structures/rome_barracks", PI, 0, 6);
187
188 // Setup some default fortress types
189 this.fortressTypes["tiny"] = new fortress("tiny");
190 var wallPart = ['entry', 'endLeft', 'wall', 'cornerIn', 'wall', 'endRight'];
191 var parts = 4;
192 for (var part = 0; part < parts; part++)
193 {
194 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
195 this.fortressTypes["tiny"].wall.push(wallPart[wallIndex])
196 };
197
198 this.fortressTypes["small"] = new fortress("small");
199 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall',
200 'cornerIn', 'wall', 'tower', 'wall', 'endRight'];
201 var parts = 4;
202 for (var part = 0; part < parts; part++)
203 {
204 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
205 this.fortressTypes["small"].wall.push(wallPart[wallIndex])
206 };
207
208 this.fortressTypes["medium"] = new fortress("medium");
209 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'cornerIn', 'wall',
210 'cornerOut', 'wall', 'cornerIn', 'wall', 'tower', 'wall', 'endRight'];
211 var parts = 4;
212 for (var part = 0; part < parts; part++)
213 {
214 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
215 this.fortressTypes["medium"].wall.push(wallPart[wallIndex])
216 };
217
218 this.fortressTypes["normal"] = new fortress("normal");
219 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'outpost', 'wall', 'cornerIn', 'wall',
220 'cornerOut', 'wall', 'cornerIn', 'wall', 'outpost', 'wall', 'tower', 'wall', 'endRight'];
221 var parts = 4;
222 for (var part = 0; part < parts; part++)
223 {
224 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
225 this.fortressTypes["normal"].wall.push(wallPart[wallIndex])
226 };
227
228 this.fortressTypes["large"] = new fortress("large");
229 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'outpost', 'wall', 'cornerIn', 'wall', 'tower', 'wall',
230 'cornerOut', 'wall', 'tower', 'wall', 'cornerIn', 'wall', 'outpost', 'wall', 'tower', 'wall', 'endRight'];
231 var parts = 4;
232 for (var part = 0; part < parts; part++)
233 {
234 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
235 this.fortressTypes["large"].wall.push(wallPart[wallIndex])
236 };
237
238 this.fortressTypes["very large"] = new fortress("very large");
239 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'outpost', 'wall',
240 'tower', 'gate', 'tower', 'wall', 'cornerIn', 'wall', 'tower', 'wall',
241 'cornerOut', 'wall', 'tower', 'wall', 'cornerIn', 'wall', 'tower', 'gate',
242 'tower', 'wall', 'outpost', 'wall', 'tower', 'wall', 'endRight'];
243 var parts = 4;
244 for (var part = 0; part < parts; part++)
245 {
246 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
247 this.fortressTypes["very large"].wall.push(wallPart[wallIndex])
248 };
249
250 this.fortressTypes["giant"] = new fortress("giant");
251 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'outpost', 'wall', 'tower',
252 'gate', 'tower', 'wall', 'cornerIn', 'wall', 'outpost', 'wall', 'tower', 'wall',
253 'cornerOut', 'wall', 'tower', 'wall', 'outpost', 'wall', 'cornerIn', 'wall', 'tower',
254 'gate', 'tower', 'wall', 'outpost', 'wall', 'tower', 'wall', 'endRight'];
255 var parts = 4;
256 for (var part = 0; part < parts; part++)
257 {
258 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
259 this.fortressTypes["giant"].wall.push(wallPart[wallIndex])
260 };
261
262 this.fortressTypes["demo"] = new fortress("demo");
263 var wallPart = ['entry', 'endLeft', 'wall', 'tower', 'wall', 'wallFort', 'wall', 'tower', 'gate', 'tower', 'wall', 'outpost',
264 'wall', 'cornerIn', 'wall', 'outpost', 'wall', 'endRight', 'wideEntry', 'endLeft', 'wall', 'tower', 'wall',
265 'cornerOut', 'wall', 'tower', 'wall', 'endRight', 'wideEntry', 'endLeft', 'wall', 'outpost', 'wall', 'cornerIn',
266 'wall', 'outpost', 'wall', 'tower', 'gate', 'tower', 'wall', 'wallFort', 'wall', 'tower', 'wall', 'endRight'];
267 var parts = 4;
268 for (var part = 0; part < parts; part++)
269 {
270 for (var wallIndex = 0; wallIndex < wallPart.length; wallIndex++)
271 this.fortressTypes["demo"].wall.push(wallPart[wallIndex]);
272 };
273
274 // Setup style
275 this.setStyle(this.style);
276
277 // Setup fortress type if preasent
278 if (this.fortress !== false && this.fortress !== undefined)
279 this.setFortressType(this.fortress);
280};
281
282wallTool.prototype.setStyle = function(style)
283{
284 if (style in this.wallStyles)
285 {
286 this.style = style;
287 this.wallTypes = this.wallStyles[style];
288 }
289 else
290 {
291 warn("Wall style '" + style + "' not found, falling back to 'palisades'...");
292 this.style = 'palisades';
293 this.wallTypes = this.wallStyles['palisades'];
294 };
295};
296
297wallTool.prototype.getAlignment = function(startX, startZ, orientation)
298{
299 if (startX == undefined)
300 startX = 0;
301 if (startZ == undefined)
302 startZ = 0;
303 if (orientation == undefined)
304 orientation = 0;
305 var wallAlignment = [];
306 var outside = orientation;
307 var wallX = startX - this.center[1]*sin(orientation) - this.center[0]*cos(orientation);
308 var wallZ = startZ - this.center[1]*cos(orientation) + this.center[0]*sin(orientation);
309 for (var iWall = 0; iWall < this.wall.length; iWall++)
310 {
311 var element = this.wallTypes[this.wall[iWall]];
312 var x = wallX - element.indent*sin(outside);
313 var z = wallZ - element.indent*cos(outside);
314 wallAlignment.push([x, z, element.entity, outside + element.angle]);
315 // Presets for the next element
316 if (iWall + 1 < this.wall.length)
317 {
318 outside += element.bending;
319 var nextElement = this.wallTypes[this.wall[iWall + 1]];
320 var distance = (element.width + nextElement.width)/2;
321 // Indent corrections for corners
322 if (element.bending !== 0 && element.indent !== 0)
323 {
324 // Indent correction of distance, not sure for non-right angles...
325 distance += element.indent*sin(element.bending);
326 // Indent correction of next normalized indentation
327 wallX += element.indent * sin(outside);
328 wallZ += element.indent * cos(outside);
329 };
330 wallX += distance * sin(outside + PI/2);
331 wallZ += distance * cos(outside + PI/2);
332 };
333 };
334 return wallAlignment
335};
336
337wallTool.prototype.getCenter = function(wallAlignment)
338{
339 var x = 0;
340 var z = 0;
341 for (var iWall = 0; iWall < wallAlignment.length; iWall++)
342 {
343 x += wallAlignment[iWall][0]/wallAlignment.length;
344 z += wallAlignment[iWall][1]/wallAlignment.length;
345 };
346 var output = [x, z];
347 return output;
348};
349
350wallTool.prototype.place = function(startX, startZ, playerId, orientation)
351{
352 var AM = this.getAlignment(startX, startZ, orientation);
353 for (var iWall = 0; iWall < this.wall.length; iWall++)
354 {
355 if (AM[iWall][2] !== undefined)
356 placeObject(AM[iWall][0], AM[iWall][1], AM[iWall][2], playerId, AM[iWall][3]);
357 };
358};
359
360wallTool.prototype.setFortressType = function(type)
361// type: A string of a default fortress type: "tiny", "small", "medium", "normal", "large", "very large", "giant"
362{
363 if (type in this.fortressTypes)
364 {
365 this.setFortress(this.fortressTypes[type]);
366 }
367 else
368 {
369 warn("Fortress type '" + type + "' not found, falling back to 'medium'");
370 this.setFortress(this.fortressTypes["medium"]);
371 };
372};
373
374wallTool.prototype.setFortress = function(fortress)
375// NOTE: If you don't set "this.calculateCenter = false" the center is recalculated and reset.
376// Fortress: An instance of a fortress class object
377{
378 this.fortress = fortress.type;
379 this.wall = fortress.wall;
380 if (this.calculateCenter == true)
381 {
382 this.center = [0, 0];
383 var AM = this.getAlignment(0, 0, 0*PI);
384 var center = this.getCenter(AM);
385 this.center = center;
386 }
387 else
388 {
389 this.center = this.fortress.center
390 };
391};
392
393wallTool.prototype.setGenericFortress = function(centerX, centerY, playerID, radius, maxBendOff, wall)
394// WARNING: This function is far from optimal!
395// radius: A float seting the aproximate radius of the fortress
396// maxBendOff: Optional, The maximum random bending offset of the wall elements NOTE: If maxBendOff > PI/2 the wall might never close!!!
397// wall: Optional, An array of wall element string, example: ["tower", "wall"] NOTE: Don't use wall elements with banding!!!
398{
399 if (wall == undefined)
400 wall = ["tower", "wall"];
401 if (maxBendOff > PI/2 || maxBendOff < 0)
402 warn("setGenericFortress maxBendOff sould satisfy 0 < maxBendOff < PI/2 (~1.5) but it is: " + maxBendOff);
403 if (maxBendOff == undefined)
404 maxBendOff = 0;
405 var wallLength = 0;
406 for (var eleIndex = 0; eleIndex < wall.length; eleIndex++)
407 {
408 wallLength += this.wallTypes[wall[eleIndex]].width
409 };
410 if (radius < wallLength || wallLength < 0)
411 warn("setGenericFortress: sum of the width of wall's elements should satisfy 0 < total length < 2*PI*radius but: radius = " + radius + ", wall = " + wall + " with total length of " + wallLength);
412
413 var minEleWidth = 1000000; // Assuming the smallest element is about as wide as deep.
414 for (var eleIndex = 0; eleIndex < wall.length; eleIndex++)
415 {
416 eleWidth = this.wallTypes[wall[eleIndex]].width;
417 if (eleWidth < minEleWidth)
418 minEleWidth = eleWidth;
419 };
420 var widthSafty = minEleWidth/4; // Can be done better...
421
422 var x = wallLength/2;
423 var y = radius;
424 var angle = 0;
425 var targetX = 0;
426 var targetY = radius;
427 var targetReached = false;
428 var eleIndex = 0;
429 this.wall = []; // not used
430 while (targetReached == false && eleIndex < 4 * 2*PI * radius / wallLength)
431 {
432 var wallElement = this.wallTypes[wall[eleIndex % wall.length]];
433 var eleWidth = wallElement.width - widthSafty;
434 var eleAddAngleOff = randFloat(-maxBendOff, maxBendOff);
435 var eleAddAngleWidth = cos(eleAddAngleOff) * eleWidth/2 / radius; // A/L = da/dl -> da = A * dl / L -> da = 2*PI * eleWidth / (2*PI * radius) -> da = eleWidth/radius
436 var eleAngleAdd = eleAddAngleWidth + eleAddAngleOff;
437 var eleAngle = angle + eleAngleAdd;
438 var placeX = x + eleWidth/2 * cos(eleAngle);
439 var placeY = y - eleWidth/2 * sin(eleAngle);
440 var placeAngle = eleAngle + wallElement.angle;
441 placeObject(centerX + placeX, centerY + placeY, wallElement.entity, playerID, placeAngle);
442 x = placeX + eleWidth/2 * cos(eleAngle);
443 y = placeY - eleWidth/2 * sin(eleAngle);
444 angle += 2*eleAddAngleWidth;
445 if (eleIndex % wall.length == 0 && eleIndex > wall.length && (getDistance(x, y, targetX, targetY) < wallLength || angle > 2*PI))
446 targetReached = true;
447 eleIndex++;
448 };
449};
450
451wallTool.prototype.placeLinearWall = function(startX, startY, targetX, targetY, playerId, wallPart, style, endWithFirst)
452// NOTE: Walls "front" or "outside" faces left when walking uppon the wall from "start" to "target".
453// startX: x coordinate of the beginning of the wall
454// startY: y coordinate of the beginning of the wall
455// targetX: x coordinate of the ending of the wall
456// targetY: y coordinate of the ending of the wall
457// NOTE: Start and target coordinates are exact meaning the wall will begin/end at the given coordinates (not the first/last entity is placed there)
458// 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)
459// wallPart: Optional. An array of wall element type strings (see wallElement.type). Default is ["wall"]
460// style: Optional. An wall style string (like defined in the "wallStyles" dictionary). Default is "palisades"
461// endWithFirst: Optional. A boolean value. If true the 1st wall element in the wallPart array will finalize the wall. Default is true
462{
463 // Setup optional arguments
464 if (playerId == undefined)
465 playerId = 0;
466 if (wallPart == undefined)
467 wallPart = ["wall"];
468 if (style == undefined)
469 if (playerId == 0) // Meaning player is gaia
470 style = "palisades"
471 else
472 style = g_MapSettings.PlayerData[playerId-1].Civ;
473 if (endWithFirst == undefined)
474 endWithFirst = true;
475 // Setup number of wall parts
476 var totalLength = getDistance(startX, startY, targetX, targetY);
477 var wallPartLength = 0;
478 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
479 wallPartLength += this.wallStyles[style][wallPart[elementIndex]].width;
480 var numParts = 0;
481 if (endWithFirst == true)
482 numParts = ceil((totalLength - this.wallStyles[style][wallPart[0]].width) / wallPartLength)
483 else
484 ceil(numParts = totalLength / wallPartLength);
485 // Setup scale factor
486 var scaleFactor = 1;
487 if (endWithFirst == true)
488 scaleFactor = totalLength / (numParts * wallPartLength + this.wallStyles[style][wallPart[0]].width)
489 else
490 scaleFactor = totalLength / (numParts * wallPartLength);
491 // Setup angle
492 var wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed...
493 var placeAngle = -wallAngle;
494 // Place wall entities
495 var x = startX;
496 var y = startY;
497 for (var partIndex = 0; partIndex < numParts; partIndex++)
498 {
499 for (var elementIndex = 0; elementIndex < wallPart.length; elementIndex++)
500 {
501 var wallEle = this.wallStyles[style][wallPart[elementIndex]];
502 x += scaleFactor * wallEle.width/2 * cos(wallAngle);
503 y += scaleFactor * wallEle.width/2 * sin(wallAngle);
504 placeObject(x, y, wallEle.entity, playerId, placeAngle + wallEle.angle);
505 x += scaleFactor * wallEle.width/2 * cos(wallAngle);
506 y += scaleFactor * wallEle.width/2 * sin(wallAngle);
507 };
508 };
509 if (endWithFirst == true)
510 {
511 var wallEle = this.wallStyles[style][wallPart[0]];
512 x += wallEle.width/2 * cos(wallAngle);
513 y += wallEle.width/2 * sin(wallAngle);
514 placeObject(x, y, wallEle.entity, playerId, placeAngle + wallEle.angle);
515 };
516};
517