1 |
|
---|
2 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
3 | // Constant definitions
|
---|
4 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
5 |
|
---|
6 | const PI = Math.PI;
|
---|
7 | const TWO_PI = 2 * Math.PI;
|
---|
8 | const TERRAIN_SEPARATOR = "|";
|
---|
9 | const SEA_LEVEL = 20.0;
|
---|
10 | const CELL_SIZE = 4;
|
---|
11 | const HEIGHT_UNITS_PER_METRE = 732;
|
---|
12 | const MIN_MAP_SIZE = 128;
|
---|
13 | const MAX_MAP_SIZE = 512;
|
---|
14 | const FALLBACK_CIV = "athen";
|
---|
15 |
|
---|
16 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
17 | // Utility functions
|
---|
18 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
19 |
|
---|
20 | function fractionToTiles(f)
|
---|
21 | {
|
---|
22 | return getMapSize() * f;
|
---|
23 | }
|
---|
24 |
|
---|
25 | function tilesToFraction(t)
|
---|
26 | {
|
---|
27 | return t / getMapSize();
|
---|
28 | }
|
---|
29 |
|
---|
30 | function fractionToSize(f)
|
---|
31 | {
|
---|
32 | return getMapArea() * f;
|
---|
33 | }
|
---|
34 |
|
---|
35 | function sizeToFraction(s)
|
---|
36 | {
|
---|
37 | return s / getMapArea();
|
---|
38 | }
|
---|
39 |
|
---|
40 | function scaleByMapSize(min, max)
|
---|
41 | {
|
---|
42 | return min + ((max-min) * (getMapSize()-MIN_MAP_SIZE) / (MAX_MAP_SIZE-MIN_MAP_SIZE));
|
---|
43 | }
|
---|
44 |
|
---|
45 | function cos(x)
|
---|
46 | {
|
---|
47 | return Math.cos(x);
|
---|
48 | }
|
---|
49 |
|
---|
50 | function sin(x)
|
---|
51 | {
|
---|
52 | return Math.sin(x);
|
---|
53 | }
|
---|
54 |
|
---|
55 | function abs(x) {
|
---|
56 | return Math.abs(x);
|
---|
57 | }
|
---|
58 |
|
---|
59 | function round(x)
|
---|
60 | {
|
---|
61 | return Math.round(x);
|
---|
62 | }
|
---|
63 |
|
---|
64 | function lerp(a, b, t)
|
---|
65 | {
|
---|
66 | return a + (b-a) * t;
|
---|
67 | }
|
---|
68 |
|
---|
69 | function sqrt(x)
|
---|
70 | {
|
---|
71 | return Math.sqrt(x);
|
---|
72 | }
|
---|
73 |
|
---|
74 | function ceil(x)
|
---|
75 | {
|
---|
76 | return Math.ceil(x);
|
---|
77 | }
|
---|
78 |
|
---|
79 | function floor(x)
|
---|
80 | {
|
---|
81 | return Math.floor(x);
|
---|
82 | }
|
---|
83 |
|
---|
84 | function max(a, b)
|
---|
85 | {
|
---|
86 | return a > b ? a : b;
|
---|
87 | }
|
---|
88 |
|
---|
89 | function min(a, b)
|
---|
90 | {
|
---|
91 | return a < b ? a : b;
|
---|
92 | }
|
---|
93 |
|
---|
94 | function println(x)
|
---|
95 | {
|
---|
96 | print(x);
|
---|
97 | print("\n");
|
---|
98 | }
|
---|
99 |
|
---|
100 | function argsToArray(x)
|
---|
101 | {
|
---|
102 | var numArgs = x.length;
|
---|
103 | if (numArgs != 1)
|
---|
104 | {
|
---|
105 | var ret = new Array(numArgs);
|
---|
106 | for (var i=0; i < numArgs; i++)
|
---|
107 | {
|
---|
108 | ret[i] = x[i];
|
---|
109 | }
|
---|
110 | return ret;
|
---|
111 | }
|
---|
112 | else
|
---|
113 | {
|
---|
114 | return x[0];
|
---|
115 | }
|
---|
116 | }
|
---|
117 |
|
---|
118 | function chooseRand()
|
---|
119 | {
|
---|
120 | if (arguments.length==0)
|
---|
121 | {
|
---|
122 | throw("chooseRand: requires at least 1 argument");
|
---|
123 | }
|
---|
124 | var ar = argsToArray(arguments);
|
---|
125 | return ar[randInt(ar.length)];
|
---|
126 | }
|
---|
127 |
|
---|
128 | // "Inside-out" implementation of Fisher-Yates shuffle
|
---|
129 | function shuffleArray(source)
|
---|
130 | {
|
---|
131 | if (!source.length)
|
---|
132 | return [];
|
---|
133 |
|
---|
134 | var result = [source[0]];
|
---|
135 | for (var i = 1; i < source.length; i++)
|
---|
136 | {
|
---|
137 | var j = randInt(0, i);
|
---|
138 | result[i] = result[j];
|
---|
139 | result[j] = source[i];
|
---|
140 | }
|
---|
141 | return result;
|
---|
142 | }
|
---|
143 |
|
---|
144 | function createAreas(centeredPlacer, painter, constraint, num, retryFactor)
|
---|
145 | {
|
---|
146 | if (retryFactor === undefined)
|
---|
147 | {
|
---|
148 | retryFactor = 10;
|
---|
149 | }
|
---|
150 |
|
---|
151 | var maxFail = num * retryFactor;
|
---|
152 | var good = 0;
|
---|
153 | var bad = 0;
|
---|
154 | var result = [];
|
---|
155 | var halfSize = getMapSize()/2;
|
---|
156 |
|
---|
157 | while(good < num && bad <= maxFail)
|
---|
158 | {
|
---|
159 | if (isCircularMap())
|
---|
160 | { // Polar coordinates
|
---|
161 | var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
|
---|
162 | var theta = randFloat(0, 2 * PI);
|
---|
163 | centeredPlacer.x = Math.floor(r * Math.cos(theta)) + halfSize;
|
---|
164 | centeredPlacer.z = Math.floor(r * Math.sin(theta)) + halfSize;
|
---|
165 | }
|
---|
166 | else
|
---|
167 | { // Rectangular coordinates
|
---|
168 | centeredPlacer.x = randInt(getMapSize());
|
---|
169 | centeredPlacer.z = randInt(getMapSize());
|
---|
170 | }
|
---|
171 |
|
---|
172 | var area = g_Map.createArea(centeredPlacer, painter, constraint);
|
---|
173 | if (area !== undefined)
|
---|
174 | {
|
---|
175 | good++;
|
---|
176 | result.push(area);
|
---|
177 | }
|
---|
178 | else
|
---|
179 | {
|
---|
180 | bad++;
|
---|
181 | }
|
---|
182 | }
|
---|
183 | return result;
|
---|
184 | }
|
---|
185 |
|
---|
186 | function createAreasInAreas(centeredPlacer, painter, constraint, num, retryFactor, areas)
|
---|
187 | {
|
---|
188 | if (retryFactor === undefined)
|
---|
189 | {
|
---|
190 | retryFactor = 10;
|
---|
191 | }
|
---|
192 |
|
---|
193 | var maxFail = num * retryFactor;
|
---|
194 | var good = 0;
|
---|
195 | var bad = 0;
|
---|
196 | var result = [];
|
---|
197 | var numAreas = areas.length;
|
---|
198 |
|
---|
199 | while(good < num && bad <= maxFail && numAreas)
|
---|
200 | {
|
---|
201 | // Choose random point from area
|
---|
202 | var i = randInt(numAreas);
|
---|
203 | var size = areas[i].points.length;
|
---|
204 | var pt = areas[i].points[randInt(size)];
|
---|
205 | centeredPlacer.x = pt.x;
|
---|
206 | centeredPlacer.z = pt.z;
|
---|
207 |
|
---|
208 | var area = g_Map.createArea(centeredPlacer, painter, constraint);
|
---|
209 | if (area !== undefined)
|
---|
210 | {
|
---|
211 | good++;
|
---|
212 | result.push(area);
|
---|
213 | }
|
---|
214 | else
|
---|
215 | {
|
---|
216 | bad++;
|
---|
217 | }
|
---|
218 | }
|
---|
219 | return result;
|
---|
220 | }
|
---|
221 |
|
---|
222 | function createObjectGroups(placer, player, constraint, num, retryFactor)
|
---|
223 | {
|
---|
224 | if (retryFactor === undefined)
|
---|
225 | {
|
---|
226 | retryFactor = 10;
|
---|
227 | }
|
---|
228 |
|
---|
229 | var maxFail = num * retryFactor;
|
---|
230 | var good = 0;
|
---|
231 | var bad = 0;
|
---|
232 | var halfSize = getMapSize()/2;
|
---|
233 | while(good < num && bad <= maxFail)
|
---|
234 | {
|
---|
235 | if (isCircularMap())
|
---|
236 | { // Polar coordinates
|
---|
237 | var r = halfSize * Math.sqrt(randFloat()); // uniform distribution
|
---|
238 | var theta = randFloat(0, 2 * PI);
|
---|
239 | placer.x = Math.floor(r * Math.cos(theta)) + halfSize;
|
---|
240 | placer.z = Math.floor(r * Math.sin(theta)) + halfSize;
|
---|
241 | }
|
---|
242 | else
|
---|
243 | { // Rectangular coordinates
|
---|
244 | placer.x = randInt(getMapSize());
|
---|
245 | placer.z = randInt(getMapSize());
|
---|
246 | }
|
---|
247 |
|
---|
248 | var result = createObjectGroup(placer, player, constraint);
|
---|
249 | if (result !== undefined)
|
---|
250 | {
|
---|
251 | good++;
|
---|
252 | }
|
---|
253 | else
|
---|
254 | {
|
---|
255 | bad++;
|
---|
256 | }
|
---|
257 | }
|
---|
258 | return good;
|
---|
259 | }
|
---|
260 |
|
---|
261 | function createObjectGroupsByAreas(placer, player, constraint, num, retryFactor, areas)
|
---|
262 | {
|
---|
263 | if (retryFactor === undefined)
|
---|
264 | {
|
---|
265 | retryFactor = 10;
|
---|
266 | }
|
---|
267 |
|
---|
268 | var maxFail = num * retryFactor;
|
---|
269 | var good = 0;
|
---|
270 | var bad = 0;
|
---|
271 | var numAreas = areas.length;
|
---|
272 |
|
---|
273 | while(good < num && bad <= maxFail && numAreas)
|
---|
274 | {
|
---|
275 | // Choose random point from area
|
---|
276 | var i = randInt(numAreas);
|
---|
277 | var size = areas[i].points.length;
|
---|
278 | var pt = areas[i].points[randInt(size)];
|
---|
279 | placer.x = pt.x;
|
---|
280 | placer.z = pt.z;
|
---|
281 |
|
---|
282 | var result = createObjectGroup(placer, player, constraint);
|
---|
283 | if (result !== undefined)
|
---|
284 | {
|
---|
285 | good++;
|
---|
286 | }
|
---|
287 | else
|
---|
288 | {
|
---|
289 | bad++;
|
---|
290 | }
|
---|
291 | }
|
---|
292 | return good;
|
---|
293 | }
|
---|
294 |
|
---|
295 | function createTerrain(terrain)
|
---|
296 | {
|
---|
297 | if (terrain instanceof Array)
|
---|
298 | {
|
---|
299 | var terrainList = [];
|
---|
300 |
|
---|
301 | for (var i = 0; i < terrain.length; ++i)
|
---|
302 | {
|
---|
303 | terrainList.push(createTerrain(terrain[i]));
|
---|
304 | }
|
---|
305 |
|
---|
306 | return new RandomTerrain(terrainList);
|
---|
307 | }
|
---|
308 | else
|
---|
309 | {
|
---|
310 | return createSimpleTerrain(terrain);
|
---|
311 | }
|
---|
312 | }
|
---|
313 |
|
---|
314 | function createSimpleTerrain(terrain)
|
---|
315 | {
|
---|
316 | if (typeof(terrain) == "string")
|
---|
317 | { // Split string by pipe | character, this allows specifying terrain + tree type in single string
|
---|
318 | var params = terrain.split(TERRAIN_SEPARATOR, 2);
|
---|
319 |
|
---|
320 | if (params.length != 2)
|
---|
321 | {
|
---|
322 | return new SimpleTerrain(terrain);
|
---|
323 | }
|
---|
324 | else
|
---|
325 | {
|
---|
326 | return new SimpleTerrain(params[0], params[1]);
|
---|
327 | }
|
---|
328 | }
|
---|
329 | else
|
---|
330 | {
|
---|
331 | throw("createSimpleTerrain expects string as input, received "+terrain);
|
---|
332 | }
|
---|
333 | }
|
---|
334 |
|
---|
335 | function placeObject(x, z, type, player, angle)
|
---|
336 | {
|
---|
337 | g_Map.addObject(new Entity(type, player, x, z, angle));
|
---|
338 | }
|
---|
339 |
|
---|
340 | function placeTerrain(x, z, terrain)
|
---|
341 | {
|
---|
342 | // convert terrain param into terrain object
|
---|
343 | g_Map.placeTerrain(x, z, createTerrain(terrain));
|
---|
344 |
|
---|
345 | }
|
---|
346 |
|
---|
347 | function isCircularMap()
|
---|
348 | {
|
---|
349 | return (g_MapSettings.CircularMap ? true : false);
|
---|
350 | }
|
---|
351 |
|
---|
352 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
353 | // Access global map variable
|
---|
354 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
355 |
|
---|
356 | function createTileClass()
|
---|
357 | {
|
---|
358 | return g_Map.createTileClass();
|
---|
359 | }
|
---|
360 |
|
---|
361 | function getTileClass(id)
|
---|
362 | {
|
---|
363 | // Check for valid class id
|
---|
364 | if (!g_Map.validClass(id))
|
---|
365 | {
|
---|
366 | return undefined;
|
---|
367 | }
|
---|
368 |
|
---|
369 | return g_Map.tileClasses[id];
|
---|
370 | }
|
---|
371 |
|
---|
372 | function createArea(placer, painter, constraint)
|
---|
373 | {
|
---|
374 | return g_Map.createArea(placer, painter, constraint);
|
---|
375 | }
|
---|
376 |
|
---|
377 | function createObjectGroup(placer, player, constraint)
|
---|
378 | {
|
---|
379 | return g_Map.createObjectGroup(placer, player, constraint);
|
---|
380 | }
|
---|
381 |
|
---|
382 | function getMapSize()
|
---|
383 | {
|
---|
384 | return g_Map.size;
|
---|
385 | }
|
---|
386 |
|
---|
387 | function getMapArea()
|
---|
388 | {
|
---|
389 | return g_Map.size*g_Map.size;
|
---|
390 | }
|
---|
391 |
|
---|
392 | function getNumPlayers()
|
---|
393 | {
|
---|
394 | return g_MapSettings.PlayerData.length;
|
---|
395 | }
|
---|
396 |
|
---|
397 | function getCivCode(player)
|
---|
398 | {
|
---|
399 | if (g_MapSettings.PlayerData[player].Civ)
|
---|
400 | return g_MapSettings.PlayerData[player].Civ;
|
---|
401 |
|
---|
402 | warn("undefined civ specified for player " + (player + 1) + ", falling back to '" + FALLBACK_CIV + "'");
|
---|
403 | return FALLBACK_CIV;
|
---|
404 | }
|
---|
405 |
|
---|
406 | function areAllies(player1, player2)
|
---|
407 | {
|
---|
408 | if ((g_MapSettings.PlayerData[player1].Team === undefined) || (g_MapSettings.PlayerData[player2].Team === undefined) || (g_MapSettings.PlayerData[player2].Team == -1) || (g_MapSettings.PlayerData[player1].Team == -1))
|
---|
409 | {
|
---|
410 | return false;
|
---|
411 | }
|
---|
412 | else
|
---|
413 | {
|
---|
414 | return (g_MapSettings.PlayerData[player1].Team === g_MapSettings.PlayerData[player2].Team);
|
---|
415 | }
|
---|
416 | }
|
---|
417 |
|
---|
418 | function getPlayerTeam(player)
|
---|
419 | {
|
---|
420 | if (g_MapSettings.PlayerData[player].Team === undefined)
|
---|
421 | {
|
---|
422 | return -1;
|
---|
423 | }
|
---|
424 | else
|
---|
425 | {
|
---|
426 | return g_MapSettings.PlayerData[player].Team;
|
---|
427 | }
|
---|
428 | }
|
---|
429 |
|
---|
430 | function sortPlayers(source)
|
---|
431 | {
|
---|
432 | if (!source.length)
|
---|
433 | return [];
|
---|
434 |
|
---|
435 | var result = new Array(0);
|
---|
436 | var team = new Array(5);
|
---|
437 | for (var q = 0; q < 5; q++)
|
---|
438 | {
|
---|
439 | team[q] = new Array(1);
|
---|
440 | }
|
---|
441 |
|
---|
442 | for (var i = -1; i < 4; i++)
|
---|
443 | {
|
---|
444 | for (var j = 0; j < source.length; j++)
|
---|
445 | {
|
---|
446 | if (getPlayerTeam(j) == i)
|
---|
447 | {
|
---|
448 | team[i+1].unshift(j+1);
|
---|
449 | }
|
---|
450 | }
|
---|
451 | team[i+1].pop();
|
---|
452 | result=result.concat(shuffleArray(team[i+1]))
|
---|
453 | }
|
---|
454 | return result;
|
---|
455 | }
|
---|
456 |
|
---|
457 | function primeSortPlayers(source)
|
---|
458 | {
|
---|
459 | if (!source.length)
|
---|
460 | return [];
|
---|
461 |
|
---|
462 | var prime = new Array(source.length);
|
---|
463 |
|
---|
464 | for (var i = 0; i < round(source.length/2); i++)
|
---|
465 | {
|
---|
466 | prime[2*i]=source[i];
|
---|
467 | prime[2*i+1]=source[source.length-1-i];
|
---|
468 | }
|
---|
469 |
|
---|
470 | return prime;
|
---|
471 | }
|
---|
472 |
|
---|
473 | function getStartingEntities(player)
|
---|
474 | {
|
---|
475 | var civ = getCivCode(player);
|
---|
476 | if (!g_CivData[civ] || !g_CivData[civ].StartEntities || !g_CivData[civ].StartEntities.length)
|
---|
477 | {
|
---|
478 | warn("Invalid or unimplemented civ '"+civ+"' specified, falling back to '" + FALLBACK_CIV + "'");
|
---|
479 | civ = FALLBACK_CIV;
|
---|
480 | }
|
---|
481 |
|
---|
482 | return g_CivData[civ].StartEntities;
|
---|
483 | }
|
---|
484 |
|
---|
485 | function getHeight(x, z)
|
---|
486 | {
|
---|
487 | return g_Map.getHeight(x, z);
|
---|
488 | }
|
---|
489 |
|
---|
490 | function setHeight(x, z, height)
|
---|
491 | {
|
---|
492 | g_Map.setHeight(x, z, height);
|
---|
493 | }
|
---|
494 |
|
---|
495 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
496 | // Utility functions for classes
|
---|
497 | /////////////////////////////////////////////////////////////////////////////////////////////
|
---|
498 |
|
---|
499 |
|
---|
500 | // Add point to given class by id
|
---|
501 | function addToClass(x, z, id)
|
---|
502 | {
|
---|
503 | var tileClass = getTileClass(id);
|
---|
504 |
|
---|
505 | if (tileClass !== null)
|
---|
506 | {
|
---|
507 | tileClass.add(x, z);
|
---|
508 | }
|
---|
509 | }
|
---|
510 |
|
---|
511 | // Remove point from the given class by id
|
---|
512 | function removeFromClass(x, z, id)
|
---|
513 | {
|
---|
514 | var tileClass = getTileClass(id);
|
---|
515 |
|
---|
516 | if (tileClass !== null)
|
---|
517 | {
|
---|
518 | tileClass.remove(x, z);
|
---|
519 | }
|
---|
520 | }
|
---|
521 |
|
---|
522 | // Create a painter for the given class
|
---|
523 | function paintClass(id)
|
---|
524 | {
|
---|
525 | return new TileClassPainter(getTileClass(id));
|
---|
526 | }
|
---|
527 |
|
---|
528 | // Create a painter for the given class
|
---|
529 | function unPaintClass(id)
|
---|
530 | {
|
---|
531 | return new TileClassUnPainter(getTileClass(id));
|
---|
532 | }
|
---|
533 |
|
---|
534 | // Create an avoid constraint for the given classes by the given distances
|
---|
535 | function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
|
---|
536 | {
|
---|
537 | var ar = new Array(arguments.length/2);
|
---|
538 | for (var i = 0; i < arguments.length/2; i++)
|
---|
539 | {
|
---|
540 | ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
|
---|
541 | }
|
---|
542 |
|
---|
543 | // Return single constraint
|
---|
544 | if (ar.length == 1)
|
---|
545 | {
|
---|
546 | return ar[0];
|
---|
547 | }
|
---|
548 | else
|
---|
549 | {
|
---|
550 | return new AndConstraint(ar);
|
---|
551 | }
|
---|
552 | }
|
---|
553 |
|
---|
554 | // Create a stay constraint for the given classes by the given distances
|
---|
555 | function stayClasses(/*class1, dist1, class2, dist2, etc*/)
|
---|
556 | {
|
---|
557 | var ar = new Array(arguments.length/2);
|
---|
558 | for (var i = 0; i < arguments.length/2; i++)
|
---|
559 | {
|
---|
560 | ar[i] = new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1]);
|
---|
561 | }
|
---|
562 |
|
---|
563 | // Return single constraint
|
---|
564 | if (ar.length == 1)
|
---|
565 | {
|
---|
566 | return ar[0];
|
---|
567 | }
|
---|
568 | else
|
---|
569 | {
|
---|
570 | return new AndConstraint(ar);
|
---|
571 | }
|
---|
572 | }
|
---|
573 |
|
---|
574 | // Create a border constraint for the given classes by the given distances
|
---|
575 | function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
|
---|
576 | {
|
---|
577 | var ar = new Array(arguments.length/3);
|
---|
578 | for (var i = 0; i < arguments.length/3; i++)
|
---|
579 | {
|
---|
580 | ar[i] = new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2]);
|
---|
581 | }
|
---|
582 |
|
---|
583 | // Return single constraint
|
---|
584 | if (ar.length == 1)
|
---|
585 | {
|
---|
586 | return ar[0];
|
---|
587 | }
|
---|
588 | else
|
---|
589 | {
|
---|
590 | return new AndConstraint(ar);
|
---|
591 | }
|
---|
592 | }
|
---|
593 |
|
---|
594 | // Checks if the given tile is in class "id"
|
---|
595 | function checkIfInClass(x, z, id)
|
---|
596 | {
|
---|
597 | var tileClass = getTileClass(id);
|
---|
598 | if (tileClass !== null)
|
---|
599 | {
|
---|
600 | if (tileClass.countMembersInRadius(x, z, 1) !== null)
|
---|
601 | {
|
---|
602 | return tileClass.countMembersInRadius(x, z, 1);
|
---|
603 | }
|
---|
604 | else
|
---|
605 | {
|
---|
606 | return 0;
|
---|
607 | }
|
---|
608 | }
|
---|
609 | else
|
---|
610 | {
|
---|
611 | return 0;
|
---|
612 | }
|
---|
613 | }
|
---|
614 |
|
---|
615 |
|
---|
616 | // Returns the distance between 2 points
|
---|
617 | function getDistance(x1, z1, x2, z2)
|
---|
618 | {
|
---|
619 | return Math.pow(Math.pow(x1 - x2, 2) + Math.pow(z1 - z2, 2), 1/2);
|
---|
620 | }
|
---|
621 |
|
---|
622 | // Returns the angle of the vector between point 1 and point 2. The angle is anticlockwise from the positive x axis.
|
---|
623 | function getAngle(x1, z1, x2, z2)
|
---|
624 | {
|
---|
625 | return Math.atan2(z2 - z1, x2 - x1);
|
---|
626 | }
|
---|
627 |
|
---|
628 | // Returns the gradient of the line between point 1 and 2 in the form dz/dx
|
---|
629 | function getGradient(x1, z1, x2, z2)
|
---|
630 | {
|
---|
631 | if (x1 == x2 && z1 == z2)
|
---|
632 | {
|
---|
633 | return 0;
|
---|
634 | }
|
---|
635 | else
|
---|
636 | {
|
---|
637 | return (z1-z2)/(x1-x2);
|
---|
638 | }
|
---|
639 | }
|
---|
640 |
|
---|
641 | function getTerrainTexture(x, y)
|
---|
642 | {
|
---|
643 | return g_Map.getTexture(x, y);
|
---|
644 | }
|
---|
645 |
|
---|