Jump to content
z80cpu

Getting Map's Max Elevation

Recommended Posts

Hello!

 

I am trying to obtain from 'run time', a means to get the highest point on ANY map.  The closest thing (command) I have found is "getTerrainHeightASL'.  But, I have to supply a position, which defeats doing this while a player is playing and I still would not know the highest spot on the map.

 

I know I can get the x/y sizes, but I do not see anywhere to get the 'z' axis/data.

 

 

What I am looking for is a way/command to do something like:

 

MaxElev = BIS_fnc_GetHighestElevation;

 

 

I could care less about the 'x/y' location, just the 'z'.

 

I would like to do this to any map while the player is playing on said map. (i.e. an universal method/command)

 

This is to create 'fog on demand' and at different height levels.  For example, in order to create a 'mountain fog', I would have to know the max height, and then take 1/3 (as an example) from that max height (1000 max - 300), then plug that number into the 'setFog' command (0 setFog [x, y, 700]).  No max height?  It would be just guessing then and kinda lame.

 

 

Any and all help is appreciated!

 

Thanks!

 

🙂

 

 

Share this post


Link to post
Share on other sites

As far as I'm aware there's nothing that does this without checking positions unfortunately, like you've said. 

  • Like 1

Share this post


Link to post
Share on other sites

Most maps contain "Hill", "RockArea" or "Viewpoint" locationsnearestLocations can find them, and locationPosition returns [x,y,z], where z is -1 * getTerrainHeightASL at the location.

 

Not a real answer I know, since there's no knowing a location would exist on the actual highest point of a particular map, but maybe something to ponder.

  • Like 3

Share this post


Link to post
Share on other sites
_max = 0;

{

    _height = getTerrainHeightASL locationPosition _x;

    if (_height > _max) then

    {

        _max = _height;

    };

} count nearestLocations [[worldSize / 2, worldsize / 2, 0], ["Hill", "Mount"], (worldSize / 2) * sqrt 2];

hint format ["max: %1", _max];

 

  • Like 2

Share this post


Link to post
Share on other sites

@beno_83au @opusfmspol @M1ke_SK - Thank you all.  It is what I was afraid of.  There is not a 'universal' method in getting the max height without an exact position being given, thus what I was wanting to avoid.

 

Though I have not tried it, for those that might be interested, there IS a way to get this value, though I suspect it would not be too quick.

 

You set up  a 'For X' loop and inside of it, a 'For Y' loop (simply put)

 

I get the x/y coords from the loop values, then get that section height.  Store this value, advance the loop and repeat.  Replace new height value when the new one is greater than the old value.

 

Have it 'step' along at something checking every 10 meters or so...

 

I suspect it would take a while to compute the whole map doing this.  BUT,  I would have the max height though.  I might try it on Stratis for the fun of it sometime.  When I do, I will be sure to report back to let ya know the outcome with the time results!

 

 

While your method is 'innovating' @M1ke_SK, what if there were no hills/mountains?  Just land like the the mid-west plains in the USA.  There are 2 maps I know of, from ?Norway? that are basically flat.  You method would not work on all maps, BUT it is a good idea though! 🙂

 

And we are on the 'same page' too with your method and mine in this post.

 

 

Thank you all again!

 

🙂

 

Share this post


Link to post
Share on other sites

You can have a look at  cfgWorlds reference.

Don't bet too much on maxHillAltitude token because it's missing on most of the maps. But you could use it like this:

 

_maxAlt = if (getNumber (configfile >> "CfgWorlds" >> worldName >> "maxHillsAltitude") >0) then [{getNumber (configfile >> "CfgWorlds" >> worldName >> "maxHillsAltitude")},{ <your code ending by the returned value>}];

 

Depending on what you intend to do, see also: fog tokens like startFogBase, haze tokens... in the link above.

 

 

 

  • Like 1

Share this post


Link to post
Share on other sites

@pierremgi - Thanks!  I will give this a try.

 

One thing I did try was my 'loop'. Strange results.  When run on Altis, it reports back the max height as 33m LESS THAN the (from what I see) is the highest spot at 312m  S/SW of ?Oreo?  (not in ARMA now).

 

And on Stratis at 'step 1', it was QUICK!  Less than 1 second to run!


 

Anybody got a reason for this?

 

Test Loop Code:

 

_size = worldSize / 2;
_stepper = 5;
_maxheight = 0;
_height = 0;

 

for "_xx" from 0 to _size step _stepper do {

 

for "_yy" from 0 to _size step _stepper do {

 

_height = getTerrainHeightASL [_xx,_yy];
if (_height > _maxheight) then {_maxheight = _height};

 

};

 

};

 

hint str _maxheight;

 

 

I tried the step at 1 (takes about 1 min) and at 5 (as shown above) and I get basically the same answer - 33m LESS than the 312 shown on map and by the cursor info.

 

Step 1 = 274m

Step 5 = 278m

Step 50 = 272m

 

 

This makes no sense to me...Icould see and accpept 311, 310, 310.5, etc.  278m?  BIG difference...  😉

 

The code does seem to work and 'step thru' every 'location' on the map.

 

????

 

Thanks for any insight and all the other help!

 

🙂

 

 

 

Share this post


Link to post
Share on other sites

_size = worldSize / 2;? That's half of the total length, so you're actually checking only one quarter of the map, right?

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, z80cpu said:

Anybody got a reason for this?

You are only scanning the lower left quarter of the map. Use _size = worldSize;

 

Resolution is going to be a problem, a way around that would be look for locations of type Mount, AFAIK they are generated at local high points by the BIS tools during the map creation process so are present on all maps, even flat ones.

 

So something like this: 

Spoiler

 

_highestASL = 0;

_center = [ worldSize / 2, worldSize / 2 ];

{

    _h = getTerrainHeightASL position _x;

    if ( _h > _highestASL ) then {

         _highestASL = _h;

    };

} forEach nearestLocations [_center, ["Mount"], _center distance2D [0,0]];

 

 

  • Like 2

Share this post


Link to post
Share on other sites

An alternative - likely worse, than checking positions grid, but fun, could be casting dense (like every 5-10 m), map-wide but terrain-only horizontal LOS checks along one axis, starting "for sure too high", then going down with halving the altitude back (if no LOS detected) and forth (if LOS unobstructed) - bracketing of sorts - and narrowing checks down to those axis values, where was terrain obstacle detected... Once you get one coord this way, second one may be obtained in few ways, for example by bracketing down LOS ray ends at this coord. 

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites

@Greenfist, @mrcurry - hahahahahaha  What a moron I was!  You are CORRECT!  I have no idea why I did that!  I will correct and let ya know!

 

What a duffus!

 

@Rydygier - EXTREMELY INTERESTING!  I never thought about doing that, but that SHOULD work!  The only issue MIGHT be if some tree/building obstructs the view, the a 'false' reading would be returned.  However, I think one could 'poll' this location somehow and ascertain if it was an object vs terrain.  It should work, I am thinking that it may take a lot longer to compute this out.  Regardless, quite interesting!

 

Thanks again to you all!

 

😉

 

  • Like 1

Share this post


Link to post
Share on other sites

Yeah, the main pro of such way is the fun of doing so. 🙂 LOS checks are heavy and when map wide? I wouldn't try to guess, how much, loading screen or without, but if you try such apporach, better prepare some eggs to fry them on that hot metal puddle, where your PC was once. Although terrain-only LOS checks could be not that heavy? BTW https://community.bistudio.com/wiki/terrainIntersect ignores any objects so there would be no false results due to that. 

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites

@beno_83au, @opusfmspol, @M1ke_SK, @pierremgi, @Greenfist, @mrcurry, @Rydygier

 

 

OK!  I got it!  Using the CORRECT mapsize...  😉  I was able to make it work fairly quick.

 

 

Here are the 'stats':

 

Using a 25m 'resolution":

 

Altis:  Real Max Height = 350m - Detected @25m = 347m - Time:  3 seconds

 

Tanoia:  Real Max Height = 443m - Detected @25m = 439m - Time:  3 seconds

 

Livonia:  Real Max Height = 442m - Detected @25m = 441m - Time:  3 seconds

 

 

Funny thing about the Livonia map, the height markers/text on the map are DEAD WRONG!  You can see this by going to the bottom SW of the map where the only building/tower is and you will see it marked as 610m, move the cursor over it and the cursor show only 442m.

 

So, I have 'solved/fixed' this question with yalls help and I do thank you for pointing out my stupid mistake!  🙂

 

 

If anybody would want the code, as it does have it uses as setting height for fog or flying things, it is below with some notation in it.  It is in  the SQF format.

 

Again thank you all!

 

🙂

 

 

 

*****

 

// Gets Map Maximum Height Of Terrain

// _MaxHeight will have the maximum height
// _mx = maximum height 'x' coordinate
// _my = maximum height 'y' coordinate

 

// Do not want marker or hint?  Delete line 'deletemarker' and ALL lines with 'MaxHeightMarker' (4) in them and delete the hintsilent line


// Deletes old marker if present
deleteMarker "MaxHight";

 

//  This is the 'resolution' that you wish to scan for. The smaller the number, the longer it will take.  Number is meters.  If set to '7' for example, it will check height every 7 meters on the map.
_stepper = 25;

 

_Size = worldSize;
_MaxHeight = 0;
_Height = 0;
_mx = 0;
_my = 0;

 

for "_xx" from 0 to _Size step _stepper do {

 

for "_yy" from 0 to _Size step _stepper do {

 

 _Height = getTerrainHeightASL [_xx,_yy];
 

if (_Height > _MaxHeight) then {_MaxHeight = _Height; _mx = _xx; _my = _yy};

 

};

 

};

 

// Places Marker Once Done
MaxHeightMarker = createmarker ["MaxHight",[_mx,_my,0]];
MaxHeightMarker setMarkerType "hd_dot";
MaxHeightMarker setMarkerColor "ColorBluFor";
MaxHeightMarker setMarkerText "Max Height";
 
 
// Shows Max Height Once Done
hintsilent str _MaxHeight;

 

  • Like 1

Share this post


Link to post
Share on other sites

Little code, perhaps faster for whole map. You can also find the highest point from a position/object within a range.

 

MGI_elevatedCheck = compileFinal "
  params ['_pos','_radius','_factor'];
  private _posTest = ATLtoASL _pos;  
  private _rangeSqr = _radius^2;  
  private _bestHigh = _posTest select 2;
  if (isNil 'MGI_posRefHighPt') then {
      MGI_posRefHighPt = _pos;
      MGI_posRefHighRange = _rangeSqr
  };
  private _n = round (_radius min worldSize / 10);
  _c = _radius / (sqrt (_n - 1));
  for '_i' from _n^_factor to 0 step -1 do {
    _rho = _c * sqrt (_i + 0.5);
    _theta = 137.508 * (_i + 0.5);
    _ckPos = _posTest getPos [_rho,_theta];
    call {
      if ((getTerrainHeightASL _ckPos) > _bestHigh && {_ckPos distanceSqr MGI_posRefHighPt < MGI_posRefHighRange}) exitWith {
        _pos = ASLtoATL _ckPos;
        _bestHigh = getTerrainHeightASL _ckPos
      };
    };
  };
  _pos
";
 
MGI_HighestPt = {
  params [["_pos",[worldSize /2,worldSize /2,0],[objNull,[]],[2,3]],["_range",worldSize/1.4]];
  _pos = if (_pos isEqualType objnull) then [{getpos _pos},{_pos}];
  _pos set [2,0];
  private _posHigh = [_pos,_range,1.5] call MGI_elevatedCheck;
  _posHigh = [_posHigh,_range /20,1.6] call MGI_elevatedCheck;
  _mk = createMarker [str random 1, _posHigh];
  _mk setMarkertype "mil_dot";
  _mk setMarkerColor "colorBlue";
  _posHigh
};

 

use it as is:
 private _highestPt =  call MGI_HighestPt; // whole map

 

or even, highest position from player within 200 m:

private _highestPt =  [player,200] call MGI_HighestPt;  // 200 around player

 

placing the player above this point:

_highestPt set [2, 1000];
player setPosASL _highestPt;
_highestPt set [2, vectorMagnitude (_highestPt vectorDiff getPosVisual player)];
player setPosASL _highestPt;


 

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

I would scan the whole map at 100m resolution, find the highest 10 points doing that, then scan 100x100 around those points at 5m resolution and take the highest point from those results.

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

@pierremgi, @Jester504 - Both interesting ideas (and good ones too).

 

I suspect some might need to know the exact height, I think this might be 'over kill' for my purpose.  I am just trying to get the 'approximate' mas height to set fog levels.  Using my method above, with the 'resolution' set at 25m, I 'scan' most maps in less than 3 seconds.  So the 'delay' is not bad.  Actually, my code runs when the mod is loaded in automatically and I can not even tell it is running it is so quick.

 

However, if someone was wanting to know the exact height, your above methods (both of you) would work.

 

@Jester504 - Your method reminds me of the old 'shell sort algorithm', which is about as old as I am...  😉

 

See: 

https://en.wikipedia.org/wiki/Shellsort

 

OR

 

Google:  shell sort algorithm

 

Thanks for yalls help!

 

🙂

 

  • Like 1

Share this post


Link to post
Share on other sites

I load up each map my mission will run on, find the maximum altitude by looking for it, then store it in a variable. 🙂

Sometimes, coding something to find a value is not the best way.

  • Like 2

Share this post


Link to post
Share on other sites

@Tankbuster

 

How do you 'look' for it?  The ways mentioned above are the only ways to get the max height.  So I am at a loss how you 'look at it'.  I am also taking about automating this process.  If you're talking about looking at the map, they can be WRONG.  The Livonia map is one where the map has the wrong heights listed.  See a post of mine from above stating this.

 

These scripts are the only accurate way to get it.  Map configs could be missing as well, so that is also useless,

 

Also, what I was after was to know the max height on ANY map as quickly as possible.  Start mission, I know height immediately.  The player has to do nothing and the height is determined in less than 3 seconds with the player not even noticing that this is being done.

 

🙂

 

Share this post


Link to post
Share on other sites
24 minutes ago, z80cpu said:

@Tankbuster

 

How do you 'look' for it?  The ways mentioned above are the only ways to get the max height.  So I am at a loss how you 'look at it'.  I am also taking about automating this process.  If you're talking about looking at the map, they can be WRONG.  The Livonia map is one where the map has the wrong heights listed.  See a post of mine from above stating this.

 

These scripts are the only accurate way to get it.  Map configs could be missing as well, so that is also useless,

 

Also, what I was after was to know the max height on ANY map as quickly as possible.  Start mission, I know height immediately.  The player has to do nothing and the height is determined in less than 3 seconds with the player not even noticing that this is being done.

 

🙂

 

By running the game, opening the editor and looking for the highest peaks. You don't need to automate everything. The couple of minutes you spend getting this information manually will soon be much shorter than the 3 seconds every time it's played.

When I've found what looks like the highest position from the editor map, spawn an entity there, run the mission and get it's z value.

 

switch (worldName) do
{
	case "Altis": {maxel = 350};// thronos
	case "Stratis": {maxel = 236};// camp maxwell
	case "Tanoa": {maxel = 443};// Mount Tanoa eastern rim
	~
	~

};

 

Share this post


Link to post
Share on other sites

@Tankbuster - While this may work, this is not want I was seeking. 

 

"...I would like to do this to any map while the player is playing on said map. (i.e. an universal method/command)..."

 

No map editing, no looking, no modules, no extra scripts, no nothing except load a mission and go.

 

If one is in the editor, one is not playing...  😉

 

Also, your method is very 'problematic' for a lot of 'flat maps'.  And who will remember all the max heights for every map they have?  And why should they when this data is used to set fog a different levels based on said heights?

 

Yes, your method would work, but must be done for every map one plays one and must be 'remembered' so how.  My method, which is listed above and does work, requires none of this and is almost instant as well as being 100% accurate.

 

As stated in my original post, this is for a mod where the player can set fog at different levels based on the map's height...ANY MAP, instantly.

 

I thank you for your time and effort in this though!

 

🙂

 

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×