diff --git a/binaries/data/mods/public/maps/random/rmgen/library.js b/binaries/data/mods/public/maps/random/rmgen/library.js index 4603fea605..024229af47 100644 --- a/binaries/data/mods/public/maps/random/rmgen/library.js +++ b/binaries/data/mods/public/maps/random/rmgen/library.js @@ -61,6 +61,23 @@ function actorTemplate(templateName) return g_ActorPrefix + templateName + ".xml"; } +function getObstructionSize(templateName, margin = 0) +{ + let obstruction = Engine.GetTemplate(templateName).Obstruction; + + let obstructionSize = + obstruction.Static ? + new Vector2D(obstruction.Static["@depth"], obstruction.Static["@width"]) : + // Used for gates, should consider the position too + obstruction.Obstructions ? + new Vector2D( + Object.keys(obstruction.Obstructions).reduce((depth, key) => Math.max(depth, +obstruction.Obstructions[key]["@depth"]), 0), + Object.keys(obstruction.Obstructions).reduce((width, key) => width + +obstruction.Obstructions[key]["@width"], 0)) : + new Vector2D(0, 0); + + return obstructionSize.div(TERRAIN_TILE_SIZE).add(new Vector2D(2, 2).mult(margin)); +} + function fractionToTiles(f) { return g_MapSettings.Size * f; diff --git a/binaries/data/mods/public/maps/random/rmgen/painter/CityPainter.js b/binaries/data/mods/public/maps/random/rmgen/painter/CityPainter.js index 34b0116f84..a81cc3f801 100644 --- a/binaries/data/mods/public/maps/random/rmgen/painter/CityPainter.js +++ b/binaries/data/mods/public/maps/random/rmgen/painter/CityPainter.js @@ -7,11 +7,7 @@ function CityPainter(templates, angle, playerID) this.playerID = playerID; this.templates = templates.map(template => { - let obstructionSize = Engine.GetTemplate(template.templateName).Obstruction.Static; - - let depth = obstructionSize["@depth"] / TERRAIN_TILE_SIZE + 2 * (template.margin || 0); - let width = obstructionSize["@width"] / TERRAIN_TILE_SIZE + 2 * (template.margin || 0); - + let obstructionSize = getObstructionSize(template.templateName, template.margin || 0); return { "templateName": template.templateName, "maxCount": template.maxCount !== undefined ? template.maxCount : Infinity, @@ -19,9 +15,9 @@ function CityPainter(templates, angle, playerID) "painter": template.painters && new MultiPainter(template.painters), "obstructionCorners": [ new Vector2D(0, 0), - new Vector2D(depth, 0), - new Vector2D(0, width), - new Vector2D(depth, width) + new Vector2D(obstructionSize.x, 0), + new Vector2D(0, obstructionSize.y), + obstructionSize ] }; }); diff --git a/binaries/data/mods/public/maps/random/rmgen/placer/noncentered/EntitiesObstructionPlacer.js b/binaries/data/mods/public/maps/random/rmgen/placer/noncentered/EntitiesObstructionPlacer.js new file mode 100644 index 0000000000..14d96cf8f0 --- /dev/null +++ b/binaries/data/mods/public/maps/random/rmgen/placer/noncentered/EntitiesObstructionPlacer.js @@ -0,0 +1,32 @@ +/** + * The EntityObstructionPlacer returns all points on the obstruction of the given template at the given position and angle that meet the constraint. + * It can be used for more concise collision avoidance. + */ +function EntitiesObstructionPlacer(entities, margin = 0, failFraction = Infinity) +{ + this.entities = entities; + this.margin = margin; + this.failFraction = failFraction; +} + +EntitiesObstructionPlacer.prototype.place = function(constraint) +{ + let points = []; + + for (let entity of this.entities) + { + let halfObstructionSize = getObstructionSize(entity.templateName, this.margin).div(2); + + // Place the entity if all points are within the boundaries and don't collide with the other entities + let obstructionCorners = [ + new Vector2D(-halfObstructionSize.x, -halfObstructionSize.y), + new Vector2D(-halfObstructionSize.x, +halfObstructionSize.y), + new Vector2D(+halfObstructionSize.x, -halfObstructionSize.y), + new Vector2D(+halfObstructionSize.x, +halfObstructionSize.y) + ].map(corner => Vector2D.add(entity.GetPosition2D(), corner.rotate(-entity.rotation.y))); + + points = points.concat(new ConvexPolygonPlacer(obstructionCorners, this.failFraction).place(constraint)) + } + + return points; +};