Jump to content
daniel-davies

Getting highest ranked player out of all playable units

Recommended Posts

Hi guys, I'm creating a function ran by the server for my multiplayer mission which will update a variable with an array containing details about the highest ranked player currently alive and in the mission. The object 'COMMAND_officer' is the highest possible ranking officer (he is the Platoon commander and the rank of Captain).

 

However if the commander dies, I need to check each playable unit to see if it is the highest ranking officer left alive on the field.

 

This is what I've wrote so far. I'm not sure if it is the best way of doing things however. 'TOUR_core' is the name of a game logic ingame.

 

fn_getHighestRankingOfficer.sqf:

if (!isNil { COMMAND_officer } ) then { exitWith { TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[COMMAND_officer, rank COMMAND_officer, name COMMAND_officer],true]; }; };

	//ALIVE LIEUTENANTS
	{
	
		if (_foundhighestOfficer == false) then {
		
		_rank = (rank _x);
		_myProfileName = name _x;
		_foundHighestOfficer = false;

		if ((rank _x) == "LIEUTENANT") exitWith { _foundHighestOfficer = true; _unitsName = (vehicle _x)};
			
		};
		
	} forEach (playableUnits+switchableUnits);
		
	if (_foundHighestOfficer == true) then {
		
			TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[_unitsName, _rank, _myProfileName],true];	
			
			_bypassOtherRankChecks = true;
		
	};
	
	////////////////////////////////////////////////////////////////
	//ALIVE SERGEANTS?
	////////////////////////////////////////////////////////////////
	if (_bypassOtherRankChecks == false) then {

		{
		
			if (_foundhighestOfficer == false) then {
				_rank = (rank _x);
				_myProfileName = name _x;
				_foundHighestOfficer = false;
			
					if ((rank _x) == "SERGEANT") exitWith { _foundHighestOfficer = true; _unitsName = (vehicle _x)};
					
			};
		
		} forEach (playableUnits+switchableUnits);
				
		if (_foundHighestOfficer == true) then {
						
				TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[_unitsName, _rank, _myProfileName],true];	
					
				_bypassOtherRankChecks = true;
					
		};
		
	};
	
	////////////////////////////////////////////////////////////////
	//ALIVE CORPORALS?
	////////////////////////////////////////////////////////////////

	if (_bypassOtherRankChecks == false) then {

		{
		
			if (_foundhighestOfficer == false) then {
				_rank = (rank _x);
				_myProfileName = name _x;
				_foundHighestOfficer = false;
			
					if ((rank _x) == "CORPORAL") exitWith { _foundHighestOfficer = true; _unitsName = (vehicle _x)};
					
			};
		
		} forEach (playableUnits+switchableUnits);
				
		if (_foundHighestOfficer == true) then {
						
				TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[_unitsName, _rank, _myProfileName],true];	
					
				_bypassOtherRankChecks = true;
					
		};
		
	};
	
	////////////////////////////////////////////////////////////////
	//ALIVE PRIVATES?????
	////////////////////////////////////////////////////////////////

	if (_bypassOtherRankChecks == false) then {

		{
		
			if (_foundhighestOfficer == false) then {
				_rank = (rank _x);
				_myProfileName = name _x;
				_foundHighestOfficer = false;
			
					if ((rank _x) == "PRIVATE") exitWith { _foundHighestOfficer = true; _unitsName = (vehicle _x)};

			};
		
		} forEach (playableUnits+switchableUnits);
				
		if (_foundHighestOfficer == true) then {
						
				TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[_unitsName, _rank, _myProfileName],true];	
					
				_bypassOtherRankChecks = true;
					
		};
		
	};

Could this be made better in any way? 

 

Thanks

Share this post


Link to post
Share on other sites

if I remember it correct then the rank depends on the rating. Wouldnt it be easier to check for those with the highest rating?

Share this post


Link to post
Share on other sites

This is what I use in my mission. the _candidate variable will be the highest ranking unit (this example loops through player units so you probably want to change that.

_candidate = objnull;

// loop through all units
{

if( isnull _candidate ) then
{
_candidate = _x;
}
else
{

if( ((rankId _x) >= (rankId _candidate)) ) then // this one limits quite a lot
{

_candidate = _x;

};
};


} foreach (units (group player));
  • Like 2

Share this post


Link to post
Share on other sites

 

This is what I use in my mission. the _candidate variable will be the highest ranking unit (this example loops through player units so you probably want to change that.

_candidate = objnull;

// loop through all units
{

if( isnull _candidate ) then
{
_candidate = _x;
}
else
{

if( ((rankId _x) >= (rankId _candidate)) ) then // this one limits quite a lot
{

_candidate = _x;

};
};


} foreach (units (group player));

 

That's far better than the code I wrote! Haha I didn't even realise there was such a thing as rankId! Thank you very much!

 

EDIT: How would I get the _candidate variable to return from the function?

Share this post


Link to post
Share on other sites

That's far better than the code I wrote! Haha I didn't even realise there was such a thing as rankId! Thank you very much!

 

EDIT: How would I get the _candidate variable to return from the function?

 

here's function version:

getHighestRankingOfficer =
{
private ["_units","_candidate"];
_units = _this;
_candidate = objnull;

// loop through all units
{

if( isnull _candidate ) then
{
_candidate = _x;
}
else
{

if( ((rankId _x) >= (rankId _candidate)) ) then // this one limits quite a lot
{

_candidate = _x;

};
};


} foreach _units;

_candidate
};

// call the function:
_man = (playableUnits+switchableUnits) call getHighestRankingOfficer;


(not tested it)

  • Like 1

Share this post


Link to post
Share on other sites

just a suggestion, not tested, not sure if it could work that way and if its faster/slower:

_highest = 0;
_highest_rank_array = _unit_array select {_highest = _highest max rankID _x; _highest == rankID _x};

_unit_array  -  the units which should be tested for the highest rank.

_highest_rank_array should have the unit with the highest rank as last element after using above code.

Share this post


Link to post
Share on other sites

Here is the thing in function form:

getHighestRankingOfficer =
{
 params ["_units"];
 private _highest = 0;
 private ["_highest_rank_array"];

 _highest_rank_array = _units select {_highest = _highest max rankID _x; _highest == rankID _x};

 (_highest_rank_array select ((count _highest_rank_array) - 1)))
};

// call the function:
_man = (playableUnits+switchableUnits) call getHighestRankingOfficer;
Edited by sarogahtyp

Share this post


Link to post
Share on other sites

Deleted

Edited by cx64

Share this post


Link to post
Share on other sites

How about...

fnc_getHighestRankingPlayer = {
    _players = ( allPlayers - entities "HeadlessClient_F" ) apply {
        if ( alive _x ) then {
            [ rankId _x, rating _x, _x ]
        } else {
            -1
        }
    };
    _players = _players - [ -1 ];
    _players sort false;
    _highestRanked = _players select 0 select 2;
    TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[ vehicle _highestRanked, rank _highestRanked, name _highestRanked],true];
};

So players are ranked via their rank and their current rating.

  • Like 2

Share this post


Link to post
Share on other sites

How about...

fnc_getHighestRankingPlayer = {
    _players = ( allPlayers - entities "HeadlessClient_F" ) apply {
        if ( alive _x ) then {
            [ rankId _x, rating _x, _x ]
        } else {
            -1
        }
    };
    _players = _players - [ -1 ];
    _players sort false;
    _highestRanked = _players select 0 select 2;
    TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[ vehicle _highestRanked, rank _highestRanked, name _highestRanked],true];
};

So players are ranked via their rank and their current rating.

Why there's no ' I love you ' button?

Share this post


Link to post
Share on other sites
Guest

Why there's no ' I love you ' button?

Yeah, I'm feeling the same every damn time.

Share this post


Link to post
Share on other sites

Amazing guys, thank you all so much! Issue is resolved :)

thats no reason to end that beautiful topic ;)

 

 

I guess that this could be faster as it does not use sort with such big arrays. But Idk...

getHighestRankingOfficer =
{
 private _highest_rank = 0;
 private _highest_rating = -99999;
 private ["_highest_rank_array", "_highestRanked"];

 //select the highest ranked players found (last element is ranked highest)
 _highest_rank_array = ((allPlayers -  entities "HeadlessClient_F") select {alive _x}) select 
 {
  _rank = rankID _x;
  _highest_rank = _highest_rank max _rank;
  (_highest_rank == _rank)
 };

 // reverse array to have highest ranked players at array start
 reverse _highest_rank_array;

 // cut the array after last player with the highest
 {
  if(rankID _x <  _highest_rank) exitWith {_highest_rank_array resize _forEachIndex};
 } forEach _highest_rank_array;

 //exit if only one player has the highest rank
 if(count _highest_rank_array == 1) exitWith 
 {
  _highestRanked = _highest_rank_array select 0;
  TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[ vehicle _highestRanked, rank _highestRanked, name _highestRanked],true];
 };

 //select the highest ranked player whith the highest rating (last element is rated highest)
 _highest_rank_array = _highest_rank_array select 
 {
  _rating = rating _x;
  _highest_rating = _highest_rating max _rating;
  (_highest_rating == _rating)
 };

  //reverse the array and select the highest ranked player with the highest rating
 _highestRanked = (reverse _highest_rank_array) select 0;

 TOUR_CORE setVariable ["DAN_var_highestRankingOfficer",[ vehicle _highestRanked, rank _highestRanked, name _highestRanked],true];
};

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

×