Ticket #4152: heightmapFix2016-12-6.patch

File heightmapFix2016-12-6.patch, 3.7 KB (added by FeXoR, 7 years ago)

Adjusted to mimo's suggestion and added optional argument playerID

  • binaries/data/mods/public/maps/random/heightmap/heightmap.js

     
    105105 * @param {integer} [minDistance=30] - How many tile widths the entities to place have to be away from each other, start locations and the map border
    106106 * @param {array} [heightmap=g_Map.height] - The reliefmap the entities should be distributed on
    107107 * @param {array} [entityList=[g_Gaia.stoneLarge, g_Gaia.metalLarge]] - Entity/actor strings to be placed with placeObject()
     108 * @param {integer} [playerID=0] - Index of the player the entities should be placed for. Gaia is 0.
    108109 * @param {integer} [maxTries=1000] - How often random player distributions are rolled to be compared
    109110 * @param {boolean} [isCircular=g_MapSettings.CircularMap] - If the map is circular or rectangular
     111 * @return {array} [placements] Array of points where entities were placed
    110112 */
    111 function distributeEntitiesByHeight(heightRange, avoidPoints, minDistance = 30, entityList = [g_Gaia.stoneLarge, g_Gaia.metalLarge], maxTries = 1000, heightmap = g_Map.height, isCircular = g_MapSettings.CircularMap)
     113function distributeEntitiesByHeight(heightRange, avoidPoints, minDistance = 30, entityList = [g_Gaia.stoneLarge, g_Gaia.metalLarge], playerID = 0, maxTries = 1000, heightmap = g_Map.height, isCircular = g_MapSettings.CircularMap)
    112114{
    113     let placements = deepcopy(avoidPoints);
    114     let validTiles = [];
     115    let validPoints = [];
    115116    let r = 0.5 * (heightmap.length - 1); // Map center x/y as well as radius
    116117    for (let x = minDistance; x < heightmap.length - minDistance; ++x)
     118    {
    117119        for (let y = minDistance; y < heightmap[0].length - minDistance; ++y)
    118             if (heightmap[x][y] > heightRange.min && heightmap[x][y] < heightRange.max) // Has the right height
    119                 if (!isCircular || r - getDistance(x, y, r, r) >= minDistance) // Is far enough away from map border
    120                     validTiles.push({ "x": x, "y": y });
     120        {
     121            if (heightmap[x][y] < heightRange.min || heightmap[x][y] > heightRange.max)
     122                continue; // Out of height range
     123            if (isCircular && r - getDistance(x + 0.5, y + 0.5, r, r) < minDistance)
     124                continue; // Too close to map border
     125            // Avoid avoidPoints by minDistance, else add to validPoints
     126            if (avoidPoints.every(ap => getDistance(x + 0.5, y + 0.5, ap.x, ap.y) > minDistance))
     127                validPoints.push({ "x": x + 0.5, "y": y + 0.5 });
     128        }
     129    }
    121130
     131    let placements = [];
     132    if (!validPoints.length)
     133    {
     134        log("No placement points found for the given arguments: " +  new Error().stack);
     135        return placements;
     136    }
     137
    122138    for (let tries = 0; tries < maxTries; ++tries)
    123139    {
    124         let tile = validTiles[randInt(validTiles.length)];
    125         let isValid = true;
    126         for (let p = 0; p < placements.length; ++p)
     140       
     141        let checkPointIndex = randInt(validPoints.length);
     142        let checkPoint = validPoints[checkPointIndex];
     143        if (placements.every(p => getDistance(p.x, p.y, checkPoint.x, checkPoint.y) > minDistance))
    127144        {
    128             if (getDistance(placements[p].x, placements[p].y, tile.x, tile.y) < minDistance)
    129             {
    130                 isValid = false;
    131                 break;
    132             }
     145            placeObject(checkPoint.x, checkPoint.y, entityList[randInt(entityList.length)], playerID, randFloat(0, 2*PI));
     146            placements.push(checkPoint);
    133147        }
    134         if (isValid)
    135         {
    136             placeObject(tile.x, tile.y, entityList[randInt(entityList.length)], 0, randFloat(0, 2*PI));
    137             placements.push(tile);
    138         }
     148       
     149        validPoints.splice(checkPointIndex);
     150        if (!validPoints.length)
     151            break; // No more valid points left
    139152    }
     153
     154    if (!placements.length)
     155        log("Nothing was placed: " +  new Error().stack);
     156
     157    return placements;
    140158}
    141159
    142160/**