diff --git a/binaries/data/mods/public/maps/random/ardennes_forest.js b/binaries/data/mods/public/maps/random/ardennes_forest.js index c4213f460e..1074c09514 100644 --- a/binaries/data/mods/public/maps/random/ardennes_forest.js +++ b/binaries/data/mods/public/maps/random/ardennes_forest.js @@ -267,7 +267,7 @@ for (var ix = 0; ix < mapSize; ix++) if (h > 35 && randBool(0.1) || h < 15 && randBool(0.05) && hillDecoClass.countMembersInRadius(ix, iz, 1) == 0) - placeObject(ix + randFloat(0, 1), iz + randFloat(0, 1), pickRandom(aTrees), 0, randomAngle()); + placeObject(Vector2D.add(position, new Vector2D(1, 1).mult(randFloat(0, 1))), pickRandom(aTrees), 0, randomAngle()); } var explorableArea = g_Map.createArea(explorablePoints); diff --git a/binaries/data/mods/public/maps/random/belgian_uplands.js b/binaries/data/mods/public/maps/random/belgian_uplands.js index 64eab79d7a..b75e14d555 100644 --- a/binaries/data/mods/public/maps/random/belgian_uplands.js +++ b/binaries/data/mods/public/maps/random/belgian_uplands.js @@ -259,7 +259,6 @@ else if (mapSize > 400) propDensity = 3/4; for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++) -{ for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; y++) { let position = new Vector2D(x, y); @@ -270,109 +269,113 @@ for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++) { createTerrain(textueByHeight[i].terrain).place(position); - // Add some props at... + let template; + if (i == 0) // ...deep water { if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/pond_lillies_large.xml", 0, randomAngle()); + template = "actor|props/flora/pond_lillies_large.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); + template = "actor|props/flora/water_lillies.xml"; } if (i == 1) // ...medium water (with fish) { if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/pond_lillies_large.xml", 0, randomAngle()); + template = "actor|props/flora/pond_lillies_large.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); + template = "actor|props/flora/water_lillies.xml"; } if (i == 2) // ...low water/mud { if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/water_log.xml", 0, randomAngle()); + template = "actor|props/flora/water_log.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); + template = "actor|props/flora/water_lillies.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); + template = "actor|geology/highland_c.xml"; else if (randBool(propDensity / 20)) - placeObject(x, y, "actor|props/flora/reeds_pond_lush_b.xml", 0, randomAngle()); + template = "actor|props/flora/reeds_pond_lush_b.xml"; else if (randBool(propDensity / 10)) - placeObject(x, y, "actor|props/flora/reeds_pond_lush_a.xml", 0, randomAngle()); + template = "actor|props/flora/reeds_pond_lush_a.xml"; } if (i == 3) // ...water suroundings/bog { if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/water_log.xml", 0, randomAngle()); + template = "actor|props/flora/water_log.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); + template = "actor|geology/highland_c.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/reeds_pond_lush_a.xml", 0, randomAngle()); + template = "actor|props/flora/reeds_pond_lush_a.xml"; } if (i == 4) // ...low height grass { if (randBool(propDensity / 800)) - placeObject(x, y, "actor|props/flora/grass_field_flowering_tall.xml", 0, randomAngle()); + template = "actor|props/flora/grass_field_flowering_tall.xml"; else if (randBool(propDensity / 400)) - placeObject(x, y, "actor|geology/gray_rock1.xml", 0, randomAngle()); + template = "actor|geology/gray_rock1.xml"; else if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/bush_tempe_sm_lush.xml", 0, randomAngle()); + template = "actor|props/flora/bush_tempe_sm_lush.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/bush_tempe_b.xml", 0, randomAngle()); + template = "actor|props/flora/bush_tempe_b.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); + template = "actor|props/flora/grass_soft_small_tall.xml"; } if (i == 5) // ...medium height grass { if (randBool(propDensity / 800)) - placeObject(x, y, "actor|geology/decal_stone_medit_a.xml", 0, randomAngle()); + template = "actor|geology/decal_stone_medit_a.xml"; else if (randBool(propDensity / 400)) - placeObject(x, y, "actor|props/flora/decals_flowers_daisies.xml", 0, randomAngle()); + template = "actor|props/flora/decals_flowers_daisies.xml"; else if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/bush_tempe_underbrush.xml", 0, randomAngle()); + template = "actor|props/flora/bush_tempe_underbrush.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); + template = "actor|props/flora/grass_soft_small_tall.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/grass_temp_field.xml", 0, randomAngle()); + template = "actor|props/flora/grass_temp_field.xml"; } if (i == 6) // ...high height grass { if (randBool(propDensity / 400)) - placeObject(x, y, "actor|geology/stone_granite_boulder.xml", 0, randomAngle()); + template = "actor|geology/stone_granite_boulder.xml"; else if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/foliagebush.xml", 0, randomAngle()); + template = "actor|props/flora/foliagebush.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/bush_tempe_underbrush.xml", 0, randomAngle()); + template = "actor|props/flora/bush_tempe_underbrush.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); + template = "actor|props/flora/grass_soft_small_tall.xml"; else if (randBool(propDensity / 20)) - placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); + template = "actor|props/flora/ferns.xml"; } if (i == 7) // ...forest border (with wood/food plants/deer/rabits) { if (randBool(propDensity / 400)) - placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); + template = "actor|geology/highland_c.xml"; else if (randBool(propDensity / 200)) - placeObject(x, y, "actor|props/flora/bush_tempe_a.xml", 0, randomAngle()); + template = "actor|props/flora/bush_tempe_a.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); + template = "actor|props/flora/ferns.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/grass_soft_tuft_a.xml", 0, randomAngle()); + template = "actor|props/flora/grass_soft_tuft_a.xml"; } if (i == 8) // ...woods { if (randBool(propDensity / 200)) - placeObject(x, y, "actor|geology/highland2_moss.xml", 0, randomAngle()); + template = "actor|geology/highland2_moss.xml"; else if (randBool(propDensity / 100)) - placeObject(x, y, "actor|props/flora/grass_soft_tuft_a.xml", 0, randomAngle()); + template = "actor|props/flora/grass_soft_tuft_a.xml"; else if (randBool(propDensity / 40)) - placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); + template = "actor|props/flora/ferns.xml"; } + + if (template) + placeObject(position, template, 0, randomAngle()); + break; } else textureMinHeight = textueByHeight[i].upperHeightLimit; } } -} Engine.SetProgress(90); @@ -404,7 +407,7 @@ else new Vector2D(-0.75 * resourceSpacing * Math.floor(resourceCount / 2), 0).rotate(-uAngle - Math.PI/2) ]); - placeObject(pos.x, pos.y, j % 2 ? "gaia/flora_tree_cypress" : "gaia/flora_bush_berry", 0, randomAngle()); + placeObject(pos, j % 2 ? "gaia/flora_tree_cypress" : "gaia/flora_bush_berry", 0, randomAngle()); } } } diff --git a/binaries/data/mods/public/maps/random/caledonian_meadows.js b/binaries/data/mods/public/maps/random/caledonian_meadows.js index 2997e38058..03e05acaa8 100644 --- a/binaries/data/mods/public/maps/random/caledonian_meadows.js +++ b/binaries/data/mods/public/maps/random/caledonian_meadows.js @@ -53,15 +53,16 @@ let decorations = [ function placeMine(point, centerEntity) { - placeObject(point.x, point.y, centerEntity, 0, randomAngle()); + placeObject(point, centerEntity, 0, randomAngle()); let quantity = randIntInclusive(11, 23); let dAngle = 2 * Math.PI / quantity; + for (let i = 0; i < quantity; ++i) - { - let angle = dAngle * randFloat(i, i + 1); - let dist = randFloat(2, 5); - placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(decorations), 0, randomAngle()); - } + placeObject( + Vector2D.add(point, new Vector2D(randFloat(2, 5), 0).rotate(-dAngle * randFloat(i, i + 1))), + pickRandom(decorations), + 0, + randomAngle()); } // Food, fences with domestic animals @@ -122,7 +123,7 @@ let clGrove = g_Map.createTileClass(); function placeGrove(point) { - placeObject(point.x, point.y, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, randomAngle()); + placeObject(point, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, randomAngle()); let quantity = randIntInclusive(20, 30); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) @@ -133,7 +134,7 @@ function placeGrove(point) if (i % 3 == 0) objectList = groveActors; let position = Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)); - placeObject(position.x, position.y, pickRandom(objectList), 0, randomAngle()); + placeObject(position, pickRandom(objectList), 0, randomAngle()); createArea( new ClumpPlacer(5, 1, 1, 1, position), [ @@ -152,14 +153,14 @@ function placeCamp(point, ] ) { - placeObject(point.x, point.y, centerEntity, 0, randomAngle()); + placeObject(point, centerEntity, 0, randomAngle()); let quantity = randIntInclusive(5, 11); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { let angle = dAngle * randFloat(i, i + 1); let dist = randFloat(1, 3); - placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(otherEntities), 0, randomAngle()); + placeObject(Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)), pickRandom(otherEntities), 0, randomAngle()); } } @@ -184,7 +185,7 @@ function placeStartLocationResources(point, foodEntities = ["gaia/flora_bush_ber if (i % 2 == 0) objectList = groveActors; let woodPosition = Vector2D.add(point, new Vector2D(randFloat(10, 15), 0).rotate(-angle)); - placeObject(woodPosition.x, woodPosition.y, pickRandom(objectList), 0, randomAngle()); + placeObject(woodPosition, pickRandom(objectList), 0, randomAngle()); createArea( new ClumpPlacer(5, 1, 1, 1, woodPosition), [ @@ -208,7 +209,7 @@ function placeStartLocationResources(point, foodEntities = ["gaia/flora_bush_ber { angle = currentAngle + randFloat(0, dAngle); let berriesPosition = Vector2D.add(point, new Vector2D(randFloat(10, 15), 0).rotate(-angle)); - placeObject(berriesPosition.x, berriesPosition.y, pickRandom(foodEntities), 0, randomAngle()); + placeObject(berriesPosition, pickRandom(foodEntities), 0, randomAngle()); currentAngle += dAngle; } } @@ -413,7 +414,7 @@ for (let h = 0; h < heighLimits.length; ++h) g_Map.setTexture(point, texture); if (actor) - placeObject(point.x + randFloat(0, 1), point.y + randFloat(0, 1), actor, 0, randomAngle()); + placeObject(Vector2D.add(point, new Vector2D(randFloat(0, 1), randFloat(0, 1))), actor, 0, randomAngle()); } Engine.SetProgress(80); @@ -423,25 +424,26 @@ if (isNomad()) else for (let p = 0; p < playerIDs.length; ++p) { - let point = startLocations[p]; - placeCivDefaultStartingEntities(point, playerIDs[p], true); - placeStartLocationResources(startLocations[p]); + let pos = new Vector2D(startLocations[p].x, startLocations[p].y); + placeCivDefaultStartingEntities(pos, playerIDs[p], true); + placeStartLocationResources(pos); } log("Placing resources, farmsteads, groves and camps..."); for (let i = 0; i < resourceSpots.length; ++i) { + let pos = new Vector2D(resourceSpots[i].x, resourceSpots[i].y); let choice = i % 5; if (choice == 0) - placeMine(resourceSpots[i], "gaia/geology_stonemine_temperate_formation"); + placeMine(pos, "gaia/geology_stonemine_temperate_formation"); if (choice == 1) - placeMine(resourceSpots[i], "gaia/geology_metal_temperate_slabs"); + placeMine(pos, "gaia/geology_metal_temperate_slabs"); if (choice == 2) - placeCustomFortress(resourceSpots[i].x, resourceSpots[i].y, pickRandom(fences), "other", 0, randomAngle()); + placeCustomFortress(pos, pickRandom(fences), "other", 0, randomAngle()); if (choice == 3) - placeGrove(resourceSpots[i]); + placeGrove(pos); if (choice == 4) - placeCamp(resourceSpots[i]); + placeCamp(pos); } g_Map.ExportMap(); diff --git a/binaries/data/mods/public/maps/random/canyon.js b/binaries/data/mods/public/maps/random/canyon.js index 9ae7dc67f8..2e4e58eba6 100644 --- a/binaries/data/mods/public/maps/random/canyon.js +++ b/binaries/data/mods/public/maps/random/canyon.js @@ -338,7 +338,7 @@ createStragglerTrees( log("Creating treasures..."); for (let i = 0; i < randIntInclusive(3, 8); ++i) for (let template of [oFoodTreasure, oWoodTreasure]) - placeObject(mapCenter.x + randFloat(-7, 7), mapCenter.y + randFloat(-7, 7), template, 0, randomAngle()); + placeObject(Vector2D.add(mapCenter, new Vector2D(randFloat(0, 7), 0).rotate(randomAngle())), template, 0, randomAngle()); placePlayersNomad( clPlayer, diff --git a/binaries/data/mods/public/maps/random/danubius.js b/binaries/data/mods/public/maps/random/danubius.js index 332eacf6f1..f00c060e25 100644 --- a/binaries/data/mods/public/maps/random/danubius.js +++ b/binaries/data/mods/public/maps/random/danubius.js @@ -298,17 +298,17 @@ if (gallicCC) new TileClassPainter(clRitualPlace) ]); - placeObject(meetingPlacePosition.x, meetingPlacePosition.y, aCampfire, 0, randomAngle()); + placeObject(meetingPlacePosition, aCampfire, 0, randomAngle()); for (let participants of ritualParticipants) { let [positions, angles] = distributePointsOnCircle(participants.count, startAngle, participants.radius * mRadius, meetingPlacePosition); for (let i = 0; i < positions.length; ++i) - placeObject(positions[i].x, positions[i].y, pickRandom(participants.templates), 0, angles[i] + participants.angle); + placeObject(positions[i], pickRandom(participants.templates), 0, angles[i] + participants.angle); } } - placeObject(civicCenterPosition.x, civicCenterPosition.y, oCivicCenter, 0, startAngle + BUILDING_ORIENTATION + Math.PI * 3/2 * i); + placeObject(civicCenterPosition, oCivicCenter, 0, startAngle + BUILDING_ORIENTATION + Math.PI * 3/2 * i); // Create the city patch createArea( @@ -319,14 +319,13 @@ if (gallicCC) ]); // Place walls and buildings - placeCustomFortress(civicCenterPosition.x, civicCenterPosition.y, fortressDanubiusVillage, "danubius_village", 0, startAngle + Math.PI); - placeCustomFortress(civicCenterPosition.x, civicCenterPosition.y, fortressDanubiusSpikes, "danubius_spikes", 0, startAngle + Math.PI); + placeCustomFortress(civicCenterPosition, fortressDanubiusVillage, "danubius_village", 0, startAngle + Math.PI); + placeCustomFortress(civicCenterPosition, fortressDanubiusSpikes, "danubius_spikes", 0, startAngle + Math.PI); // Place treasure, potentially inside buildings for (let i = 0; i < gallicCCTreasureCount; ++i) placeObject( - civicCenterPosition.x + randFloat(-0.8, 0.8) * gaulCityRadius, - civicCenterPosition.y + randFloat(-0.8, 0.8) * gaulCityRadius, + Vector2D.add(civicCenterPosition, new Vector2D(randFloat(-1, 1) * 0.8 * gaulCityRadius, 0).rotate(randomAngle())), pickRandom(oTreasures), 0, randomAngle()); @@ -715,8 +714,8 @@ for (let i = 0; i < 2; ++i) log("Creating patrol points for land attackers..."); addToClass(mapCenter.x, mapCenter.y, clMiddle); -var riverDirectionPosition = Vector2D.add(mapCenter, new Vector2D(0, 1).rotate(startAngle)); -placeObject(riverDirectionPosition.x, riverDirectionPosition.y, triggerPointRiverDirection, 0, 0); +log("Creating triggerpoint to allow the triggerscript to determine the river direction..."); +placeObject(Vector2D.add(mapCenter, new Vector2D(0, 1).rotate(startAngle)), triggerPointRiverDirection, 0, 0); for (let i = 0; i < 2; ++i) { diff --git a/binaries/data/mods/public/maps/random/deep_forest.js b/binaries/data/mods/public/maps/random/deep_forest.js index c469f57c35..3ee139520e 100644 --- a/binaries/data/mods/public/maps/random/deep_forest.js +++ b/binaries/data/mods/public/maps/random/deep_forest.js @@ -134,7 +134,7 @@ for (let i = 0; i < numPlayers; ++i) let angle = playerAngle[i] + angleDist * (rIndex + 1) / (resourcePerPlayer.length + 1); let position = Vector2D.add(mapCenter, new Vector2D(resourceRadius, 0).rotate(-angle)).round(); - placeObject(position.x, position.y, resourcePerPlayer[rIndex], 0, randomAngle()); + placeObject(position, resourcePerPlayer[rIndex], 0, randomAngle()); createArea( new ClumpPlacer(40, 1/2, 1/8, 1, position), @@ -147,7 +147,7 @@ for (let i = 0; i < numPlayers; ++i) Engine.SetProgress(60); log("Placing temple..."); -placeObject(mapCenter.x, mapCenter.y, templateTemple, 0, randomAngle()); +placeObject(mapCenter, templateTemple, 0, randomAngle()); addToClass(mapCenter.x, mapCenter.y, clBaseResource); log("Creating central mountain..."); diff --git a/binaries/data/mods/public/maps/random/fortress.js b/binaries/data/mods/public/maps/random/fortress.js index 95e6422020..cfb69d006f 100644 --- a/binaries/data/mods/public/maps/random/fortress.js +++ b/binaries/data/mods/public/maps/random/fortress.js @@ -132,7 +132,7 @@ for (let i = 0; i < numPlayers; ++i) "cornerIn", "long", "house", "tower", "long", "tower", "long", "cornerIn", "long", "house", "tower"]; } - placeCustomFortress(playerPosition[i].x, playerPosition[i].y, new Fortress("Spahbod", wall), civ, playerIDs[i], -Math.PI/4); + placeCustomFortress(playerPosition[i], new Fortress("Spahbod", wall), civ, playerIDs[i], -Math.PI/4); } log("Creating lakes..."); diff --git a/binaries/data/mods/public/maps/random/islands.js b/binaries/data/mods/public/maps/random/islands.js index 8d1e9df419..3a559dd955 100644 --- a/binaries/data/mods/public/maps/random/islands.js +++ b/binaries/data/mods/public/maps/random/islands.js @@ -84,7 +84,7 @@ if (!isNomad()) ]); let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , heightLand - 0.5, heightLand); - placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); + placeObject(dockLocation, oDock, playerIDs[i], playerAngle[i] + Math.PI); } } diff --git a/binaries/data/mods/public/maps/random/latium.js b/binaries/data/mods/public/maps/random/latium.js index 470784f103..228d6c8c67 100644 --- a/binaries/data/mods/public/maps/random/latium.js +++ b/binaries/data/mods/public/maps/random/latium.js @@ -304,14 +304,14 @@ for (var ix = 0; ix < mapSize; ix++) { t = (diffH > 1.2) ? tGrassCliff : tGrassDry; if (diffH < 0.5 && randBool(0.02)) - placeObject(randFloat(ix, ix + 1), randFloat(iz, iz + 1), aGrassDry, 0, randomAngle()); + placeObject(Vector2D.add(position, new Vector2D(1, 1).mult(randFloat(0, 1))), aGrassDry, 0, randomAngle()); } else if (grassNoise > 0.61) { t = (diffH > 1.2 ? tGrassRock : tGrassShrubs); } else if (diffH < 0.5 && randBool(0.02)) - placeObject(randFloat(ix, ix + 1), randFloat(iz, iz + 1), aGrass, 0, randomAngle()); + placeObject(Vector2D.add(position, new Vector2D(1, 1).mult(randFloat(0, 1))), aGrass, 0, randomAngle()); } createTerrain(t).place(position); diff --git a/binaries/data/mods/public/maps/random/migration.js b/binaries/data/mods/public/maps/random/migration.js index 24daee41aa..43a13d54b4 100644 --- a/binaries/data/mods/public/maps/random/migration.js +++ b/binaries/data/mods/public/maps/random/migration.js @@ -87,7 +87,7 @@ for (let i = 0; i < numPlayers; ++i) continue; let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , 2.6, 3); - placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); + placeObject(dockLocation, oDock, playerIDs[i], playerAngle[i] + Math.PI); } Engine.SetProgress(10); diff --git a/binaries/data/mods/public/maps/random/polar_sea.js b/binaries/data/mods/public/maps/random/polar_sea.js index 50c86fcb1c..3ac42ab029 100644 --- a/binaries/data/mods/public/maps/random/polar_sea.js +++ b/binaries/data/mods/public/maps/random/polar_sea.js @@ -59,7 +59,7 @@ if (!isNomad()) for (let i = 0; i < numPlayers; ++i) { let marketPos = Vector2D.add(playerPosition[i], new Vector2D(12, 0).rotate(randomAngle())).round(); - placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION); + placeObject(marketPos, oMarket, playerIDs[i], BUILDING_ORIENTATION); addCivicCenterAreaToClass(marketPos, clBaseResource); } diff --git a/binaries/data/mods/public/maps/random/rmgen/gaia_entities.js b/binaries/data/mods/public/maps/random/rmgen/gaia_entities.js index 08d93a208d..e381dbfa49 100644 --- a/binaries/data/mods/public/maps/random/rmgen/gaia_entities.js +++ b/binaries/data/mods/public/maps/random/rmgen/gaia_entities.js @@ -92,7 +92,7 @@ function createStoneMineFormation(position, templateName, terrain, radius = 2.5, for (let i = 0; i < count; ++i) { let pos = Vector2D.add(position, new Vector2D(radius + randFloat(0, maxOffset), 0).rotate(-angle)).round(); - placeObject(pos.x, pos.y, templateName, 0, randomAngle()); + placeObject(pos, templateName, 0, randomAngle()); angle += 3/2 * Math.PI / count; } } diff --git a/binaries/data/mods/public/maps/random/rmgen/library.js b/binaries/data/mods/public/maps/random/rmgen/library.js index 21c59f3e46..7806052d69 100644 --- a/binaries/data/mods/public/maps/random/rmgen/library.js +++ b/binaries/data/mods/public/maps/random/rmgen/library.js @@ -183,11 +183,10 @@ function createTerrain(terrain) new RandomTerrain(terrain.map(t => createTerrain(t))); } -function placeObject(x, z, type, player, angle) +function placeObject(position, type, player, angle) { - let position = new Vector2D(x, z); if (g_Map.validTile(position)) - g_Map.addObject(new Entity(type, player, x, z, angle)); + g_Map.addObject(new Entity(type, player, position.x, position.y, angle)); } function getTileClass(id) diff --git a/binaries/data/mods/public/maps/random/rmgen/player.js b/binaries/data/mods/public/maps/random/rmgen/player.js index d9f8a2b33e..aed3e7cccc 100644 --- a/binaries/data/mods/public/maps/random/rmgen/player.js +++ b/binaries/data/mods/public/maps/random/rmgen/player.js @@ -79,7 +79,7 @@ function placeStartingEntities(location, playerID, civEntities, dist = 6, orient let firstTemplate = civEntities[i].Template; if (firstTemplate.startsWith("structures/")) { - placeObject(location.x, location.y, firstTemplate, playerID, orientation); + placeObject(location, firstTemplate, playerID, orientation); ++i; } @@ -91,38 +91,41 @@ function placeStartingEntities(location, playerID, civEntities, dist = 6, orient let count = civEntities[j].Count || 1; for (let num = 0; num < count; ++num) - placeObject( - location.x + dist * Math.cos(angle) + space * (-num + 0.75 * Math.floor(count / 2)) * Math.sin(angle), - location.y + dist * Math.sin(angle) + space * (num - 0.75 * Math.floor(count / 2)) * Math.cos(angle), - civEntities[j].Template, - playerID, - angle); + { + let position = Vector2D.sum([ + location, + new Vector2D(dist, 0).rotate(-angle), + new Vector2D(space * (-num + 0.75 * Math.floor(count / 2)), 0).rotate(angle) + ]); + + placeObject(position, civEntities[j].Template, playerID, angle); + } } } /** * Places the default starting entities as defined by the civilization definition, optionally including city walls. */ -function placeCivDefaultStartingEntities(location, playerID, wallType, dist = 6, orientation = BUILDING_ORIENTATION) +function placeCivDefaultStartingEntities(position, playerID, wallType, dist = 6, orientation = BUILDING_ORIENTATION) { - placeStartingEntities(location, playerID, getStartingEntities(playerID), dist, orientation); - placeStartingWalls(location.x, location.y, playerID, wallType, orientation); + placeStartingEntities(position, playerID, getStartingEntities(playerID), dist, orientation); + placeStartingWalls(position, playerID, wallType, orientation); } /** * If the map is large enough and the civilization defines them, places the initial city walls or towers. * @param {string|boolean} wallType - Either "towers" to only place the wall turrets or a boolean indicating enclosing city walls. */ -function placeStartingWalls(x, z, playerID, wallType, orientation = BUILDING_ORIENTATION) +function placeStartingWalls(position, playerID, wallType, orientation = BUILDING_ORIENTATION) { let civ = getCivCode(playerID); if (civ != "iber" || g_Map.getSize() <= 128) return; if (wallType == "towers") - placePolygonalWall(x, z, 15, ["entry"], "tower", civ, playerID, orientation, 7); + placePolygonalWall(position, 15, ["entry"], "tower", civ, playerID, orientation, 7); else if (wallType) - placeGenericFortress(x, z, 20, playerID); + placeGenericFortress(position, 20, playerID); } /** diff --git a/binaries/data/mods/public/maps/random/rmgen/wall_builder.js b/binaries/data/mods/public/maps/random/rmgen/wall_builder.js index cef436727c..af5dc859fb 100644 --- a/binaries/data/mods/public/maps/random/rmgen/wall_builder.js +++ b/binaries/data/mods/public/maps/random/rmgen/wall_builder.js @@ -279,19 +279,17 @@ function readyWallElement(path, civCode) * Placing the first wall element at startX/startY placed with an angle given by orientation * An alignment can be used to get the "center" of a "wall" (more likely used for fortresses) with getCenterToFirstElement * - * @param {number} startX - * @param {number} startY + * @param {Vector2D} position * @param {array} [wall] * @param {string} [style] * @param {number} [orientation] * @returns {array} */ -function getWallAlignment(startX, startY, wall = [], style = "athen_stone", orientation = 0) +function getWallAlignment(position, wall = [], style = "athen_stone", orientation = 0) { style = validateStyle(style); let alignment = []; - let wallX = startX; - let wallY = startY; + let wallPosition = position.clone(); for (let i = 0; i < wall.length; ++i) { @@ -302,14 +300,9 @@ function getWallAlignment(startX, startY, wall = [], style = "athen_stone", orie continue; } - // Indentation - let placeX = wallX - element.indent * Math.cos(orientation); - let placeY = wallY - element.indent * Math.sin(orientation); - // Add wall elements entity placement arguments to the alignment alignment.push({ - "x": placeX, - "y": placeY, + "position": Vector2D.sub(wallPosition, new Vector2D(element.indent, 0).rotate(-orientation)), "templateName": element.templateName, "angle": orientation + element.angle }); @@ -336,12 +329,11 @@ function getWallAlignment(startX, startY, wall = [], style = "athen_stone", orie distance += indent * Math.sin(bend); // Indent correction to normalize indentation - wallX += indent * Math.cos(orientation); - wallY += indent * Math.sin(orientation); + wallPosition.add(new Vector2D(indent).rotate(-orientation)); } + // Set the next coordinates of the next element in the wall without indentation adjustment - wallX -= distance * Math.sin(orientation); - wallY += distance * Math.cos(orientation); + wallPosition.add(new Vector2D(distance, 0).rotate(-orientation).perpendicular()); } } return alignment; @@ -357,13 +349,7 @@ function getWallAlignment(startX, startY, wall = [], style = "athen_stone", orie */ function getCenterToFirstElement(alignment) { - let centerToFirstElement = { "x": 0, "y": 0 }; - for (let align of alignment) - { - centerToFirstElement.x -= align.x / alignment.length; - centerToFirstElement.y -= align.y / alignment.length; - } - return centerToFirstElement; + return alignment.reduce((result, align) => result.sub(Vector2D.div(align.position, alignment.length)), new Vector2D(0, 0)); } /** @@ -412,8 +398,7 @@ function validateStyle(style, playerId = 0) /** * Places an abitrary wall beginning at the location comprised of the array of elements provided. * - * @param {number} startX - * @param {number} startY + * @param {Vector2D} position * @param {array} [wall] - Array of wall element types. Example: ["start", "long", "tower", "long", "end"] * @param {string} [style] - Wall style string. * @param {number} [playerId] - Identifier of the player for whom the wall will be placed. @@ -422,14 +407,13 @@ function validateStyle(style, playerId = 0) * It will then be build towards top/positive Y (if no bending wall elements like corners are used) * Raising orientation means the wall is rotated counter-clockwise like placeObject */ -function placeWall(startX, startY, wall = [], style, playerId = 0, orientation = 0) +function placeWall(position, wall = [], style, playerId = 0, orientation = 0) { style = validateStyle(style, playerId); - let AM = getWallAlignment(startX, startY, wall, style, orientation); - for (let iWall = 0; iWall < wall.length; ++iWall) - if (AM[iWall].templateName) - placeObject(AM[iWall].x, AM[iWall].y, AM[iWall].templateName, playerId, AM[iWall].angle); + for (let align of getWallAlignment(position, wall, style, orientation)) + if (align.templateName) + placeObject(align.position, align.templateName, playerId, align.angle); } /** @@ -439,14 +423,13 @@ function placeWall(startX, startY, wall = [], style, playerId = 0, orientation = * The fortress wall should always start with the main entrance (like * "entry" or "gate") to get the orientation correct. * - * @param {number} centerX - * @param {number} centerY + * @param {Vector2D} centerPosition * @param {object} [fortress] - If not provided, defaults to the predefined "medium" fortress type. * @param {string} [style] - Wall style string. * @param {number} [playerId] - Identifier of the player for whom the wall will be placed. * @param {number} [orientation] - Angle the first wall element (should be a gate or entrance) is placed. Default is 0 */ -function placeCustomFortress(centerX, centerY, fortress, style, playerId = 0, orientation = 0) +function placeCustomFortress(centerPosition, fortress, style, playerId = 0, orientation = 0) { fortress = fortress || g_FortressTypes.medium; style = validateStyle(style, playerId); @@ -454,12 +437,16 @@ function placeCustomFortress(centerX, centerY, fortress, style, playerId = 0, or // Calculate center if fortress.centerToFirstElement is undefined (default) let centerToFirstElement = fortress.centerToFirstElement; if (centerToFirstElement === undefined) - centerToFirstElement = getCenterToFirstElement(getWallAlignment(0, 0, fortress.wall, style)); + centerToFirstElement = getCenterToFirstElement(getWallAlignment(new Vector2D(0, 0), fortress.wall, style)); // Placing the fortress wall - let startX = centerX + centerToFirstElement.x * Math.cos(orientation) - centerToFirstElement.y * Math.sin(orientation); - let startY = centerY + centerToFirstElement.y * Math.cos(orientation) + centerToFirstElement.x * Math.sin(orientation); - placeWall(startX, startY, fortress.wall, style, playerId, orientation); + let position = Vector2D.sum([ + centerPosition, + new Vector2D(centerToFirstElement.x, 0).rotate(-orientation), + new Vector2D(centerToFirstElement.y, 0).perpendicular().rotate(-orientation) + ]); + + placeWall(position, fortress.wall, style, playerId, orientation); } /** @@ -469,10 +456,9 @@ function placeCustomFortress(centerX, centerY, fortress, style, playerId = 0, or * * @param {string} [type] - Predefined fortress type, as used as a key in g_FortressTypes. */ -function placeFortress(centerX, centerY, type = "medium", style, playerId = 0, orientation = 0) +function placeFortress(centerPosition, type = "medium", style, playerId = 0, orientation = 0) { - // Call placeCustomFortress with the given arguments - placeCustomFortress(centerX, centerY, g_FortressTypes[type], style, playerId, orientation); + placeCustomFortress(centerPosition, g_FortressTypes[type], style, playerId, orientation); } /** @@ -481,15 +467,13 @@ function placeFortress(centerX, centerY, type = "medium", style, playerId = 0, o * * Note: Any "bending" wall pieces passed will be complained about. * - * @param {number} startX - Approximate start point of the wall. - * @param {number} startY - Approximate start point of the wall. - * @param {number} targetX - Approximate end point of the wall. - * @param {number} targetY - Approximate end point of the wall. + * @param {Vector2D} startPosition - Approximate start point of the wall. + * @param {Vector2D} targetPosition - Approximate end point of the wall. * @param {array} [wallPart=["tower", "long"]] * @param {number} [playerId] * @param {boolean} [endWithFirst] - If true, the first wall element will also be the last. */ -function placeLinearWall(startX, startY, targetX, targetY, wallPart = undefined, style, playerId = 0, endWithFirst = true) +function placeLinearWall(startPosition, targetPosition, wallPart = undefined, style, playerId = 0, endWithFirst = true) { wallPart = wallPart || ["tower", "long"]; style = validateStyle(style, playerId); @@ -501,7 +485,7 @@ function placeLinearWall(startX, startY, targetX, targetY, wallPart = undefined, // Setup number of wall parts - let totalLength = Math.euclidDistance2D(startX, startY, targetX, targetY); + let totalLength = startPosition.distanceTo(targetPosition); let wallPartLength = getWallLength(style, wallPart); let numParts = Math.ceil(totalLength / wallPartLength); if (endWithFirst) @@ -513,47 +497,39 @@ function placeLinearWall(startX, startY, targetX, targetY, wallPart = undefined, scaleFactor = totalLength / (numParts * wallPartLength + getWallElement(wallPart[0], style).length); // Setup angle - let wallAngle = getAngle(startX, startY, targetX, targetY); // NOTE: function "getAngle()" is about to be changed... + let wallAngle = getAngle(startPosition.x, startPosition.y, targetPosition.x, targetPosition.y); let placeAngle = wallAngle - Math.PI / 2; // Place wall entities - let x = startX; - let y = startY; + let position = startPosition.clone(); let overlap = g_WallStyles[style].overlap; for (let partIndex = 0; partIndex < numParts; ++partIndex) - { for (let elementIndex = 0; elementIndex < wallPart.length; ++elementIndex) { let wallEle = getWallElement(wallPart[elementIndex], style); + let wallLength = (wallEle.length - overlap) / 2; - let distX = scaleFactor * wallLength * Math.cos(wallAngle); - let distY = scaleFactor * wallLength * Math.sin(wallAngle); + let dist = new Vector2D(scaleFactor * wallLength, 0).rotate(-wallAngle); // Length correction - x += distX; - y += distY; + position.add(dist); // Indent correction - let placeX = x - wallEle.indent * Math.sin(wallAngle); - let placeY = y + wallEle.indent * Math.cos(wallAngle); + let place = Vector2D.add(position, new Vector2D(0, wallEle.indent).rotate(-wallAngle)); - // Placement if (wallEle.templateName) - placeObject(placeX, placeY, wallEle.templateName, playerId, placeAngle + wallEle.angle); + placeObject(place, wallEle.templateName, playerId, placeAngle + wallEle.angle); - // Prep for next object - x += distX; - y += distY; + position.add(dist); } - } + if (endWithFirst) { let wallEle = getWallElement(wallPart[0], style); let wallLength = (wallEle.length - overlap) / 2; - x += scaleFactor * wallLength * Math.cos(wallAngle); - y += scaleFactor * wallLength * Math.sin(wallAngle); + position.add(new Vector2D(scaleFactor * wallLength, 0).rotate(-wallAngle)); if (wallEle.templateName) - placeObject(x, y, wallEle.templateName, playerId, placeAngle + wallEle.angle); + placeObject(position, wallEle.templateName, playerId, placeAngle + wallEle.angle); } } @@ -568,8 +544,7 @@ function placeLinearWall(startX, startY, targetX, targetY, wallPart = undefined, * * Note: Any "bending" wall pieces passed will be complained about. * - * @param {number} centerX - Center of the circle or arc. - * @param {number} centerY - Center of the circle or arc. + * @param {Vector2D} center - Center of the circle or arc. * @param (number} radius - Approximate radius of the circle. (Given the maxBendOff argument) * @param {array} [wallPart] * @param {string} [style] @@ -579,7 +554,7 @@ function placeLinearWall(startX, startY, targetX, targetY, wallPart = undefined, * @param {boolean} [endWithFirst] - If true, the first wall element will also be the last. For full circles, the default is false. For arcs, true. * @param {number} [maxBendOff] Optional. How irregular the circle should be. 0 means regular circle, PI/2 means very irregular. Default is 0 (regular circle) */ -function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId = 0, orientation = 0, maxAngle = Math.PI * 2, endWithFirst, maxBendOff = 0) +function placeCircularWall(center, radius, wallPart, style, playerId = 0, orientation = 0, maxAngle = Math.PI * 2, endWithFirst, maxBendOff = 0) { wallPart = wallPart || ["tower", "long"]; style = validateStyle(style, playerId); @@ -609,8 +584,7 @@ function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId = // Place wall entities let actualAngle = orientation + (Math.PI * 2 - maxAngle) / 2; - let x = centerX + radius * Math.cos(actualAngle); - let y = centerY + radius * Math.sin(actualAngle); + let position = Vector2D.add(center, new Vector2D(radius, 0).rotate(-actualAngle)); let overlap = g_WallStyles[style].overlap; for (let partIndex = 0; partIndex < numParts; ++partIndex) for (let wallEle of wallPart) @@ -619,36 +593,30 @@ function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId = // Width correction let addAngle = scaleFactor * (wallEle.length - overlap) / radius; - let targetX = centerX + radius * Math.cos(actualAngle + addAngle); - let targetY = centerY + radius * Math.sin(actualAngle + addAngle); - let placeX = x + (targetX - x) / 2; - let placeY = y + (targetY - y) / 2; + let target = Vector2D.add(center, new Vector2D(radius, 0).rotate(-actualAngle - addAngle)); + let place = Vector2D.average([position, target]); let placeAngle = actualAngle + addAngle / 2; // Indent correction - placeX -= wallEle.indent * Math.cos(placeAngle); - placeY -= wallEle.indent * Math.sin(placeAngle); + place.sub(new Vector2D(wallEle.indent, 0).rotate(-placeAngle)); // Placement if (wallEle.templateName) - placeObject(placeX, placeY, wallEle.templateName, playerId, placeAngle + wallEle.angle); + placeObject(place, wallEle.templateName, playerId, placeAngle + wallEle.angle); // Prepare for the next wall element actualAngle += addAngle; - x = centerX + radius * Math.cos(actualAngle); - y = centerY + radius * Math.sin(actualAngle); + position = Vector2D.add(center, new Vector2D(radius, 0).rotate(-actualAngle)); } if (endWithFirst) { let wallEle = getWallElement(wallPart[0], style); let addAngle = scaleFactor * wallEle.length / radius; - let targetX = centerX + radius * Math.cos(actualAngle + addAngle); - let targetY = centerY + radius * Math.sin(actualAngle + addAngle); - let placeX = x + (targetX - x) / 2; - let placeY = y + (targetY - y) / 2; + let target = Vector2D.add(center, new Vector2D(radius, 0).rotate(-actualAngle - addAngle)) + let place = Vector2D.average([position, target]); let placeAngle = actualAngle + addAngle / 2; - placeObject(placeX, placeY, wallEle.templateName, playerId, placeAngle + wallEle.angle); + placeObject(place, wallEle.templateName, playerId, placeAngle + wallEle.angle); } } @@ -658,8 +626,7 @@ function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId = * * Note: Any "bending" wall pieces passed will be ignored. * - * @param {number} centerX - * @param {number} centerY + * @param {Vector2D} centerPosition * @param {number} radius * @param {array} [wallPart] * @param {string} [cornerWallElement] - Wall element to be placed at the polygon's corners. @@ -669,42 +636,35 @@ function placeCircularWall(centerX, centerY, radius, wallPart, style, playerId = * @param {number} [numCorners] - How many corners the polygon will have. * @param {boolean} [skipFirstWall] - If the first linear wall part will be left opened as entrance. */ -function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElement = "tower", style, playerId = 0, orientation = 0, numCorners = 8, skipFirstWall = true) +function placePolygonalWall(centerPosition, radius, wallPart, cornerWallElement = "tower", style, playerId = 0, orientation = 0, numCorners = 8, skipFirstWall = true) { wallPart = wallPart || ["long", "tower"]; style = validateStyle(style, playerId); - // Setup angles let angleAdd = Math.PI * 2 / numCorners; let angleStart = orientation - angleAdd / 2; + let corners = new Array(numCorners).fill(0).map((zero, i) => + Vector2D.add(centerPosition, new Vector2D(radius, 0).rotate(-angleStart - i * angleAdd))); - // Setup corners - let corners = []; - for (let i = 0; i < numCorners; ++i) - corners.push([ - centerX + radius * Math.cos(angleStart + i * angleAdd), - centerY + radius * Math.sin(angleStart + i * angleAdd) - ]); - - // Place Corners and walls for (let i = 0; i < numCorners; ++i) { - let angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY); - placeObject(corners[i][0], corners[i][1], getWallElement(cornerWallElement, style).templateName, playerId, angleToCorner); + let angleToCorner = getAngle(corners[i].x, corners[i].y, centerPosition.x, centerPosition.y); + placeObject(corners[i], getWallElement(cornerWallElement, style).templateName, playerId, angleToCorner); + if (!skipFirstWall || i != 0) { let cornerLength = getWallElement(cornerWallElement, style).length / 2; let cornerAngle = angleToCorner + angleAdd / 2; - let cornerX = cornerLength * Math.sin(cornerAngle); - let cornerY = cornerLength * Math.cos(cornerAngle); let targetCorner = (i + 1) % numCorners; + let cornerPosition = new Vector2D(cornerLength, 0).rotate(-cornerAngle).perpendicular(); + placeLinearWall( // Adjustment to the corner element width (approximately) - corners[i][0] + cornerX, // startX - corners[i][1] - cornerY, // startY - corners[targetCorner][0] - cornerX, // targetX - corners[targetCorner][1] + cornerY, // targetY - wallPart, style, playerId); + Vector2D.sub(corners[i], cornerPosition), + Vector2D.add(corners[targetCorner], cornerPosition), + wallPart, + style, + playerId); } } } @@ -718,8 +678,7 @@ function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen * * Note: The wallPartsAssortment is last because it's the hardest to set. * - * @param {number} centerX - * @param {number} centerY + * @param {Vector2D} centerPosition * @param {number} radius * @param {string} [cornerWallElement] - Wall element to be placed at the polygon's corners. * @param {string} [style] @@ -730,7 +689,7 @@ function placePolygonalWall(centerX, centerY, radius, wallPart, cornerWallElemen * @param {boolean} [skipFirstWall] - If true, the first linear wall part will be left open as an entrance. * @param {array} [wallPartsAssortment] - An array of wall part arrays to choose from for each linear wall connecting the corners. */ -function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement = "tower", style, playerId = 0, orientation = 0, numCorners, irregularity = 0.5, skipFirstWall = false, wallPartsAssortment) +function placeIrregularPolygonalWall(centerPosition, radius, cornerWallElement = "tower", style, playerId = 0, orientation = 0, numCorners, irregularity = 0.5, skipFirstWall = false, wallPartsAssortment) { style = validateStyle(style, playerId); numCorners = numCorners || randIntInclusive(5, 7); @@ -775,10 +734,8 @@ function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement let angleActual = orientation - angleAddList[0] / 2; for (let i = 0; i < numCorners; ++i) { - corners.push([ - centerX + radius * Math.cos(angleActual), - centerY + radius * Math.sin(angleActual) - ]); + corners.push(Vector2D.add(centerPosition, new Vector2D(radius, 0).rotate(-angleActual))); + if (i < numCorners - 1) angleActual += angleAddList[i + 1]; } @@ -801,7 +758,7 @@ function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement let bestWallLength = Infinity; let targetCorner = (i + 1) % numCorners; // NOTE: This is not quite the length the wall will be in the end. Has to be tweaked... - let wallLength = Math.euclidDistance2D(corners[i][0], corners[i][1], corners[targetCorner][0], corners[targetCorner][1]); + let wallLength = corners[i].distanceTo(corners[targetCorner]); let numWallParts = Math.ceil(wallLength / maxWallPartLength); for (let partIndex = 0; partIndex < wallPartsAssortment.length; ++partIndex) { @@ -818,21 +775,24 @@ function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement // Place Corners and walls for (let i = 0; i < numCorners; ++i) { - let angleToCorner = getAngle(corners[i][0], corners[i][1], centerX, centerY); - placeObject(corners[i][0], corners[i][1], getWallElement(cornerWallElement, style).templateName, playerId, angleToCorner); + let angleToCorner = getAngle(corners[i].x, corners[i].y, centerPosition.x, centerPosition.y); + placeObject(corners[i], getWallElement(cornerWallElement, style).templateName, playerId, angleToCorner); if (!skipFirstWall || i != 0) { let cornerLength = getWallElement(cornerWallElement, style).length / 2; let targetCorner = (i + 1) % numCorners; let startAngle = angleToCorner + angleAddList[i] / 2; let targetAngle = angleToCorner + angleAddList[targetCorner] / 2; + + placeLinearWall( // Adjustment to the corner element width (approximately) - corners[i][0] + cornerLength * Math.sin(startAngle), // startX - corners[i][1] - cornerLength * Math.cos(startAngle), // startY - corners[targetCorner][0] - cornerLength * Math.sin(targetAngle), // targetX - corners[targetCorner][1] + cornerLength * Math.cos(targetAngle), // targetY - wallPartList[i], style, playerId, false); + Vector2D.sub(corners[i], new Vector2D(cornerLength, 0).perpendicular().rotate(-startAngle)), + Vector2D.add(corners[targetCorner], new Vector2D(cornerLength, 0).rotate(-targetAngle - Math.PI / 2)), + wallPartList[i], + style, + playerId, + false); } } } @@ -848,23 +808,21 @@ function placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement * * This is the default Iberian civ bonus starting wall. * - * @param {number} centerX - The approximate center coordinates of the fortress - * @param {number} centerY - The approximate center coordinates of the fortress + * @param {Vector2D} center - The approximate center coordinates of the fortress * @param {number} [radius] - The approximate radius of the wall to be placed. * @param {number} [playerId] * @param {string} [style] * @param {number} [irregularity] - 0 = circle, 1 = very spiky * @param {number} [gateOccurence] - Integer number, every n-th walls will be a gate instead. - * @param {number} [maxTrys] - How often the function tries to find a better fitting shape. + * @param {number} [maxTries] - How often the function tries to find a better fitting shape. */ -function placeGenericFortress(centerX, centerY, radius = 20, playerId = 0, style, irregularity = 0.5, gateOccurence = 3, maxTrys = 100) +function placeGenericFortress(center, radius = 20, playerId = 0, style, irregularity = 0.5, gateOccurence = 3, maxTries = 100) { style = validateStyle(style, playerId); // Setup some vars - let startAngle = randFloat(0, Math.PI * 2); - let actualOffX = radius * Math.cos(startAngle); - let actualOffY = radius * Math.sin(startAngle); + let startAngle = randomAngle(); + let actualOff = new Vector2D(radius, 0).rotate(-startAngle); let actualAngle = startAngle; let pointDistance = getWallLength(style, ["long", "tower"]); @@ -873,33 +831,31 @@ function placeGenericFortress(centerX, centerY, radius = 20, playerId = 0, style let bestPointDerivation; let minOverlap = 1000; let overlap; - while (tries < maxTrys && minOverlap > g_WallStyles[style].overlap) + while (tries < maxTries && minOverlap > g_WallStyles[style].overlap) { let pointDerivation = []; let distanceToTarget = 1000; - let targetReached = false; - while (!targetReached) + while (true) { let indent = randFloat(-irregularity * pointDistance, irregularity * pointDistance); - let tmpAngle = getAngle(actualOffX, actualOffY, - (radius + indent) * Math.cos(actualAngle + pointDistance / radius), - (radius + indent) * Math.sin(actualAngle + pointDistance / radius) - ); - actualOffX += pointDistance * Math.cos(tmpAngle); - actualOffY += pointDistance * Math.sin(tmpAngle); - actualAngle = getAngle(0, 0, actualOffX, actualOffY); - pointDerivation.push([actualOffX, actualOffY]); - distanceToTarget = Math.euclidDistance2D(actualOffX, actualOffY, ...pointDerivation[0]); + let tmp = new Vector2D(radius + indent, 0).rotate(-actualAngle - pointDistance / radius); + let tmpAngle = getAngle(actualOff.x, actualOff.y, tmp.x, tmp.y); + + actualOff.add(new Vector2D(pointDistance, 0).rotate(-tmpAngle)); + actualAngle = getAngle(0, 0, actualOff.x, actualOff.y); + pointDerivation.push(actualOff.clone()); + distanceToTarget = pointDerivation[0].distanceTo(actualOff); + let numPoints = pointDerivation.length; if (numPoints > 3 && distanceToTarget < pointDistance) // Could be done better... { - targetReached = true; - overlap = pointDistance - Math.euclidDistance2D(...pointDerivation[numPoints - 1], ...pointDerivation[0]); + overlap = pointDistance - pointDerivation[numPoints - 1].distanceTo(pointDerivation[0]); if (overlap < minOverlap) { minOverlap = overlap; bestPointDerivation = pointDerivation; } + break; } } ++tries; @@ -909,34 +865,24 @@ function placeGenericFortress(centerX, centerY, radius = 20, playerId = 0, style // Place wall for (let pointIndex = 0; pointIndex < bestPointDerivation.length; ++pointIndex) { - let startX = centerX + bestPointDerivation[pointIndex][0]; - let startY = centerY + bestPointDerivation[pointIndex][1]; - let targetX = centerX + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][0]; - let targetY = centerY + bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length][1]; - let angle = getAngle(startX, startY, targetX, targetY); + let start = Vector2D.add(center, bestPointDerivation[pointIndex]); + let target = Vector2D.add(center, bestPointDerivation[(pointIndex + 1) % bestPointDerivation.length]); + let angle = getAngle(start.x, start.y, target.x, target.y); let element = (pointIndex + 1) % gateOccurence == 0 ? "gate" : "long"; element = getWallElement(element, style); + if (element.templateName) { - let dist = Math.euclidDistance2D(startX, startY, targetX, targetY) / 2; - placeObject( - startX + dist * Math.cos(angle), // placeX - startY + dist * Math.sin(angle), // placeY - element.templateName, playerId, angle - Math.PI / 2 + element.angle - ); + let pos = Vector2D.add(start, new Vector2D(start.distanceTo(target) / 2, 0).rotate(-angle)); + placeObject(pos, element.templateName, playerId, angle - Math.PI / 2 + element.angle); } // Place tower - startX = centerX + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][0]; - startY = centerY + bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length][1]; - angle = getAngle(startX, startY, targetX, targetY); + start = Vector2D.add(center, bestPointDerivation[(pointIndex + bestPointDerivation.length - 1) % bestPointDerivation.length]); + angle = getAngle(start.x, start.y, target.x, target.y); let tower = getWallElement("tower", style); - placeObject( - centerX + bestPointDerivation[pointIndex][0], - centerY + bestPointDerivation[pointIndex][1], - tower.templateName, playerId, angle - Math.PI / 2 + tower.angle - ); + placeObject(Vector2D.add(center, bestPointDerivation[pointIndex]), tower.templateName, playerId, angle - Math.PI / 2 + tower.angle); } } diff --git a/binaries/data/mods/public/maps/random/survivalofthefittest.js b/binaries/data/mods/public/maps/random/survivalofthefittest.js index 29526e49f6..fd2ce6a8b8 100644 --- a/binaries/data/mods/public/maps/random/survivalofthefittest.js +++ b/binaries/data/mods/public/maps/random/survivalofthefittest.js @@ -94,11 +94,11 @@ for (let i = 0; i < numPlayers; ++i) log("Placing treasure seeker woman..."); let femaleLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , 3.5, 3).round(); addToClass(femaleLocation.x, femaleLocation.y, clWomen); - placeObject(femaleLocation.x, femaleLocation.y, oTreasureSeeker, playerIDs[i], playerAngle[i] + Math.PI); + placeObject(femaleLocation, oTreasureSeeker, playerIDs[i], playerAngle[i] + Math.PI); log("Placing attacker spawn point...."); - placeObject(attacker[i].x, attacker[i].y, aWaypointFlag, 0, Math.PI / 2); - placeObject(attacker[i].x, attacker[i].y, triggerPointAttacker, playerIDs[i], Math.PI / 2); + placeObject(attacker[i], aWaypointFlag, 0, Math.PI / 2); + placeObject(attacker[i], triggerPointAttacker, playerIDs[i], Math.PI / 2); log("Preventing mountains in the area between player and attackers..."); addCivicCenterAreaToClass(playerPosition[i], clPlayer); diff --git a/binaries/data/mods/public/maps/random/the_nile.js b/binaries/data/mods/public/maps/random/the_nile.js index ceb4f5c353..e69357587d 100644 --- a/binaries/data/mods/public/maps/random/the_nile.js +++ b/binaries/data/mods/public/maps/random/the_nile.js @@ -155,7 +155,7 @@ paintRiver({ if (plantID % plantFrequency == 0) { plantID = 0; - placeObject(position.x, position.y, aPlants, 0, randomAngle()); + placeObject(position, aPlants, 0, randomAngle()); } ++plantID; }, diff --git a/binaries/data/mods/public/maps/random/wall_demo.js b/binaries/data/mods/public/maps/random/wall_demo.js index d6cf5d51f0..c7d7b0a838 100644 --- a/binaries/data/mods/public/maps/random/wall_demo.js +++ b/binaries/data/mods/public/maps/random/wall_demo.js @@ -50,8 +50,8 @@ var mapSize = g_Map.getSize(); const distToMapBorder = 5; const distToOtherWalls = 10; var buildableMapSize = mapSize - 2 * distToMapBorder; -var actualX = distToMapBorder; -var actualY = distToMapBorder; + +var position = new Vector2D(distToMapBorder, distToMapBorder); var playerID = 0; const wallStyleList = Object.keys(g_WallStyles); @@ -69,18 +69,14 @@ const wallStyleList = Object.keys(g_WallStyles); */ for (let styleIndex in wallStyleList) { - let x = actualX + styleIndex * buildableMapSize / wallStyleList.length; - let y = actualY; + let pos = Vector2D.add(position, new Vector2D(styleIndex * buildableMapSize / wallStyleList.length)); let wall = ['start', 'long', 'tower', 'tower', 'tower', 'medium', 'outpost', 'medium', 'cornerOut', 'medium', 'cornerIn', 'medium', 'house', 'end', 'entryTower', 'start', 'short', 'barracks', 'gate', 'tower', 'medium', 'fort', 'medium', 'end']; let style = wallStyleList[styleIndex]; let orientation = Math.PI / 16 * Math.sin(styleIndex * Math.PI / 4); - - placeWall(x, y, wall, style, playerID, orientation); + placeWall(pos, wall, style, playerID, orientation); } -// Prep for next set of walls -actualX = distToMapBorder; -actualY += 80 + distToOtherWalls; +position.y += 80 + distToOtherWalls; /** * Default fortress placement (chosen by fortress type string) @@ -100,19 +96,21 @@ var fortressRadius = 15; // The space the fortresses take in average. Just for d for (let styleIndex in wallStyleList) { - let x = actualX + fortressRadius + styleIndex * buildableMapSize / wallStyleList.length; - let y = actualY + fortressRadius; let type = "tiny"; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 32; - placeObject(x, y, "other/obelisk", playerID, orientation); - placeFortress(x, y, type, style, playerID, orientation); + let pos = Vector2D.sum([ + position, + new Vector2D(1, 1).mult(fortressRadius), + new Vector2D(styleIndex * buildableMapSize / wallStyleList.length, 0) + ]); + + placeObject(pos, "other/obelisk", playerID, orientation); + placeFortress(pos, type, style, playerID, orientation); } -// Prep for next set of walls -actualX = distToMapBorder; -actualY += 2 * fortressRadius + distToOtherWalls; +position.y += 2 * fortressRadius + distToOtherWalls; /** * 'Generic' fortress placement (iberian wall circuit code) @@ -125,20 +123,22 @@ actualY += 2 * fortressRadius + distToOtherWalls; * * We also supply a radius value to dictate how wide the circuit of walls should be. */ -var radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); +var radius = Math.min((mapSize - position.y - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { - let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; - let centerY = actualY + radius; let style = wallStyleList[styleIndex]; - placeObject(centerX, centerY, 'other/obelisk', playerID, 0); - placeGenericFortress(centerX, centerY, radius, playerID, style); + let pos = Vector2D.sum([ + position, + new Vector2D(radius, radius), + new Vector2D(styleIndex * buildableMapSize / wallStyleList.length, 0) + ]); + + placeObject(pos, "other/obelisk", playerID, 0); + placeGenericFortress(pos, radius, playerID, style); } -// Prep for next set of walls -actualX = distToMapBorder; -actualY += 2 * radius + distToOtherWalls; +position.y += 2 * radius + distToOtherWalls; /** * Circular wall placement @@ -162,11 +162,10 @@ actualY += 2 * radius + distToOtherWalls; * arc faces. If the wall is to be a complete circle, then this is used as * the orientation of the first wall piece. */ -radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); +radius = Math.min((mapSize - position.y - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { - let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; - let centerY = actualY + radius; + let center = Vector2D.sum([position, new Vector2D(1, 1).mult(radius), new Vector2D(styleIndex * buildableMapSize / wallStyleList.length, 0)]); let wallPart = ['tower', 'medium', 'house']; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 16; @@ -176,13 +175,11 @@ for (let styleIndex in wallStyleList) // If less than Pi * 2, then the wall will be an arc. let maxAngle = Math.PI / 2 * (styleIndex % 3 + 2); - placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); - placeCircularWall(centerX, centerY, radius, wallPart, style, playerID, orientation, maxAngle); + placeObject(center, "other/obelisk", playerID, orientation); + placeCircularWall(center, radius, wallPart, style, playerID, orientation, maxAngle); } -// Prep for next set of walls. -actualX = distToMapBorder; -actualY += 2 * radius + distToOtherWalls; +position.y += 2 * radius + distToOtherWalls; /** * Regular Polygonal wall placement @@ -208,11 +205,11 @@ actualY += 2 * radius + distToOtherWalls; * outward side facing or, if the `skipFirstWall` argument is true, the * opening in the wall. */ -radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); + +radius = Math.min((mapSize - position.y - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { - let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; - let centerY = actualY + radius; + let centerPosition = Vector2D.sum([position, new Vector2D(1, 1).mult(radius), new Vector2D(styleIndex * buildableMapSize / wallStyleList.length, 0)]); let wallParts = ['medium', 'tower']; // Function default: ['long', 'tower'] // Which wall element to use for the corners of the polygon @@ -227,13 +224,11 @@ for (let styleIndex in wallStyleList) // If true, the first side will not be drawn, leaving the wall open. let skipFirstWall = true; - placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); - placePolygonalWall(centerX, centerY, radius, wallParts, cornerWallElement, style, playerID, orientation, numCorners, skipFirstWall); + placeObject(centerPosition, "other/obelisk", playerID, orientation); + placePolygonalWall(centerPosition, radius, wallParts, cornerWallElement, style, playerID, orientation, numCorners, skipFirstWall); } -// Prep for next set of walls. -actualX = distToMapBorder; -actualY += 2 * radius + distToOtherWalls; +position.y += 2 * radius + distToOtherWalls; /** * Irregular Polygonal wall placement @@ -263,11 +258,14 @@ actualY += 2 * radius + distToOtherWalls; * the wall. It is not defined in this example (so as to use the defaults) * as it is not easy to comprehend. */ -radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons +radius = Math.min((mapSize - position.y - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons for (let styleIndex in wallStyleList) { - let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; - let centerY = actualY + radius; + let centerPosition = Vector2D.sum([ + position, + new Vector2D(1, 1).mult(radius), + new Vector2D(styleIndex * buildableMapSize / wallStyleList.length, 0) + ]); // Which wall element type will be used for the corners of the polygon. let cornerWallElement = 'tower'; @@ -284,13 +282,11 @@ for (let styleIndex in wallStyleList) // If true, the first side will not be drawn, leaving the wall open. let skipFirstWall = true; - placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); - placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerID, orientation, numCorners, irregularity, skipFirstWall); + placeObject(centerPosition, "other/obelisk", playerID, orientation); + placeIrregularPolygonalWall(centerPosition, radius, cornerWallElement, style, playerID, orientation, numCorners, irregularity, skipFirstWall); } -// Prep for next set of walls. -actualX = distToMapBorder; -actualY += 2 * radius + distToOtherWalls; +position.y += 2 * radius + distToOtherWalls; /** * Linear wall placement @@ -306,25 +302,20 @@ actualY += 2 * radius + distToOtherWalls; * of the walls is facing the top of the screen. */ // Two vars, just for this map; firstly how long the longest wall will be. -var maxWallLength = (mapSize - actualY - distToMapBorder - distToOtherWalls); +var maxWallLength = (mapSize - position.y - distToMapBorder - distToOtherWalls); // And secondly, how many walls of the same style will be placed. var numWallsPerStyle = Math.floor(buildableMapSize / distToOtherWalls / wallStyleList.length); for (let styleIndex in wallStyleList) for (let wallIndex = 0; wallIndex < numWallsPerStyle; ++wallIndex) { - // Start point. - let startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * buildableMapSize / wallStyleList.length / numWallsPerStyle; - let startY = actualY; + let offsetX = (styleIndex * numWallsPerStyle + wallIndex) * buildableMapSize / wallStyleList.length / numWallsPerStyle; + let start = Vector2D.add(position, new Vector2D(offsetX, 0)); - // End point. - let endX = startX; - let endY = actualY + (wallIndex + 1) * maxWallLength / numWallsPerStyle; + let offsetY = (wallIndex + 1) * maxWallLength / numWallsPerStyle; + let end = Vector2D.add(position, new Vector2D(offsetX, offsetY)); - let wallPart = ['tower', 'medium']; - let style = wallStyleList[styleIndex]; - - placeLinearWall(startX, startY, endX, endY, wallPart, style, playerID); + placeLinearWall(start, end, ['tower', 'medium'], wallStyleList[styleIndex], playerID); } g_Map.ExportMap(); diff --git a/binaries/data/mods/public/maps/random/wild_lake.js b/binaries/data/mods/public/maps/random/wild_lake.js index 8bab05dd98..d3f6fed782 100644 --- a/binaries/data/mods/public/maps/random/wild_lake.js +++ b/binaries/data/mods/public/maps/random/wild_lake.js @@ -203,8 +203,7 @@ var mercenaryCampGuards = { * Resource spots and other points of interest */ -// Mines -function placeMine(point, centerEntity, +function placeMine(position, centerEntity, decorativeActors = [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, @@ -212,15 +211,16 @@ function placeMine(point, centerEntity, ] ) { - placeObject(point.x, point.y, centerEntity, 0, randomAngle()); + placeObject(position, centerEntity, 0, randomAngle()); + let quantity = randIntInclusive(11, 23); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) - { - let angle = dAngle * randFloat(i, i + 1); - let dist = randFloat(2, 5); - placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(decorativeActors), 0, randomAngle()); - } + placeObject( + Vector2D.add(position, new Vector2D(randFloat(2, 5), 0).rotate(-dAngle * randFloat(i, i + 1))), + pickRandom(decorativeActors), + 0, + randomAngle()); } // Groves, only Wood @@ -238,7 +238,9 @@ function placeGrove(point, groveTerrainTexture = getArray(g_Terrains.forestFloor1) ) { - placeObject(point.x, point.y, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, randomAngle()); + let position = new Vector2D(point.x, point.y); + placeObject(position, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, randomAngle()); + let quantity = randIntInclusive(20, 30); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) @@ -249,15 +251,15 @@ function placeGrove(point, if (i % 3 == 0) objectList = groveActors; - let position = Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)); - placeObject(position.x, position.y, pickRandom(objectList), 0, randomAngle()); + let pos = Vector2D.add(position, new Vector2D(dist, 0).rotate(-angle)); + placeObject(pos, pickRandom(objectList), 0, randomAngle()); let painters = [new TerrainPainter(groveTerrainTexture)]; if (groveTileClass) painters.push(new TileClassPainter(groveTileClass)); createArea( - new ClumpPlacer(5, 1, 1, 1, position), + new ClumpPlacer(5, 1, 1, 1, pos), painters); } } @@ -320,7 +322,7 @@ for (let i = 0; i < num; ++i) fences.push(new Fortress("fence", clone(fences[i].wall).reverse())); // Camps with fire and gold treasure -function placeCamp(point, +function placeCamp(position, centerEntity = "actor|props/special/eyecandy/campfire.xml", otherEntities = ["gaia/special_treasure_metal", "gaia/special_treasure_standing_stone", "units/brit_infantry_slinger_b", "units/brit_infantry_javelinist_b", "units/gaul_infantry_slinger_b", "units/gaul_infantry_javelinist_b", "units/gaul_champion_fanatic", @@ -328,14 +330,15 @@ function placeCamp(point, ] ) { - placeObject(point.x, point.y, centerEntity, 0, randomAngle()); + placeObject(position, centerEntity, 0, randomAngle()); + let quantity = randIntInclusive(5, 11); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { let angle = dAngle * randFloat(i, i + 1); let dist = randFloat(1, 3); - placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(otherEntities), 0, randomAngle()); + placeObject(Vector2D.add(position, new Vector2D(dist, 0).rotate(-angle)), pickRandom(otherEntities), 0, randomAngle()); } } @@ -362,7 +365,7 @@ function placeStartLocationResources( // Stone let dAngle = 4/9 * Math.PI; let angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); - placeMine({ "x": point.x + averageDistToCC * Math.cos(angle), "y": point.y + averageDistToCC * Math.sin(angle) }, g_Gaia.stoneLarge); + placeMine(Vector2D.add(point, new Vector2D(averageDistToCC, 0).rotate(-angle)), g_Gaia.stoneLarge); currentAngle += dAngle; @@ -378,7 +381,7 @@ function placeStartLocationResources( objectList = groveActors; let position = Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)); - placeObject(position.x, position.y, pickRandom(objectList), 0, randomAngle()); + placeObject(position, pickRandom(objectList), 0, randomAngle()); createArea( new ClumpPlacer(5, 1, 1, 1, position), [ @@ -392,7 +395,7 @@ function placeStartLocationResources( // Metal dAngle = 4/9 * Math.PI; angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); - placeMine({ "x": point.x + averageDistToCC * Math.cos(angle), "y": point.y + averageDistToCC * Math.sin(angle) }, g_Gaia.metalLarge); + placeMine(Vector2D.add(point, new Vector2D(averageDistToCC, 0).rotate(-angle)), g_Gaia.metalLarge); currentAngle += dAngle; // Berries and domestic animals @@ -402,7 +405,7 @@ function placeStartLocationResources( { angle = currentAngle + randFloat(0, dAngle); let dist = getRandDist(); - placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(foodEntities), 0, randomAngle()); + placeObject(Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)), pickRandom(foodEntities), 0, randomAngle()); currentAngle += dAngle; } } @@ -580,7 +583,7 @@ for (let h = 0; h < heighLimits.length; ++h) g_Map.setTexture(point, texture); if (actor) - placeObject(point.x + randFloat(0, 1), point.y + randFloat(0, 1), actor, 0, randomAngle()); + placeObject(Vector2D.add(point, new Vector2D(randFloat(0, 1), randFloat(0, 1))), actor, 0, randomAngle()); } Engine.SetProgress(80); @@ -588,7 +591,8 @@ log("Placing resources..."); let avoidPoints = clone(startLocations); for (let i = 0; i < avoidPoints.length; ++i) avoidPoints[i].dist = 30; -let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints, clPath); +let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints, clPath).map(point => new Vector2D(point.x, point.y)); + Engine.SetProgress(55); log("Placing players..."); @@ -597,7 +601,7 @@ if (isNomad()) else for (let p = 0; p < playerIDs.length; ++p) { - let point = startLocations[p]; + let point = new Vector2D(startLocations[p].x, startLocations[p].y); placeCivDefaultStartingEntities(point, playerIDs[p], g_Map.size > 192); placeStartLocationResources(point); } @@ -628,7 +632,7 @@ for (let i = 0; i < resourceSpots.length; ++i) } else { - placeCustomFortress(resourceSpots[i].x, resourceSpots[i].y, pickRandom(fences), "other", 0, randomAngle()); + placeCustomFortress(resourceSpots[i], pickRandom(fences), "other", 0, randomAngle()); rectangularSmoothToHeight(resourceSpots[i], 10, 10, g_Map.getHeight(resourceSpots[i]), 0.5); } }