Jump to content
HonzaVinCZ

[Help] Custom Vehicle Markers

Recommended Posts

Hey guys, I need you to help me with this script. Basically this script creates markers on selected vehicles and makes markers move with vehicles. Problem with this script is, that it cannot find target vehicle after vehicle was destroyed and respawned by other script I'm attaching under my actual script. It even won't work if vehicle name is set in editor. 
Any idea how could I make marker find vehicle again, change text to not destroyed and move with that vehicle again please? 

scripts\VehicleMarkers.sqf

Spoiler

/*
Vehicle init
marker = [this,1,1] execVM "scripts\VehicleMarkers.sqf";

- vehicle
- text
- side

Vehicle:
this or vehicle name

Text:
1 = Repair Truck
2 = Fuel Truck
3 = Ammo Truck
4 = MHQ
5 = MEDEVAC

Side:
1 = BLUFOR
2 = OPFOR
3 = INDEPEMENT


*/

_unit = _this select 0;
_text = _this select 1;
_side = _this select 2;
_randomnumber = random 1000000;

_nameMarkerWEST = "MarkernameWEST" + (str _randomnumber);
_nameMarkerEAST = "MarkernameEAST" + (str _randomnumber);
_nameMarkerIND = "MarkernameIND" + (str _randomnumber);

if (_side == 1) then {
	createMarker [_nameMarkerWEST, getPosVisual _unit];
	_nameMarkerWEST setMarkerColor "colorBLUFOR";
};

if (_side == 2) then {
	createMarker [_nameMarkerEAST, getPosVisual _unit];
	_nameMarkerEAST setMarkerColor "colorOPFOR";
};

if (_side == 3) then {
	createMarker [_nameMarkerIND, getPosVisual _unit];
	_nameMarkerIND setMarkerColor "colorIndepement";
};

if (_text == 1 or _text == 2 or _text == 3) then {
	{_x setMarkerType "b_unknown"} forEach [_nameMarkerWEST,_nameMarkerEAST,_nameMarkerIND];
};

if (_text == 4) then {
	{_x setMarkerType "b_hq"} forEach [_nameMarkerWEST,_nameMarkerEAST,_nameMarkerIND];
};

if (_text == 5) then {
	{_x setMarkerType "b_med"} forEach [_nameMarkerWEST,_nameMarkerEAST,_nameMarkerIND];
};

{_x setMarkerAlphaLocal 0} forEach [_nameMarkerWEST,_nameMarkerEAST,_nameMarkerIND];
switch (side player) do 
{
	case WEST: 
	{
		{_x setMarkerAlphaLocal 1} forEach [_nameMarkerWEST];
	};
	case EAST: 
	{
		{_x setMarkerAlphaLocal 1} forEach [_nameMarkerEAST];
	};
	case IND: 
	{
		{_x setMarkerAlphaLocal 1} forEach [_nameMarkerIND];
	};
};

while {true} do {

	switch (_side) do {

		case 1:
		{
			switch (_text) do {

				case 1:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "Repair truck";
					} else {
						_nameMarkerWEST setMarkerText "Repair truck is destroyed";
					};
				};

				case 2:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "Fuel truck";
					} else {
						_nameMarkerWEST setMarkerText "Fuel truck is destroyed";
					};
				};

				case 3:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "Ammo truck";
					} else {
						_nameMarkerWEST setMarkerText "Ammo truck is destroyed";
					};
				};

				case 4:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "HQ";
					} else {
						_nameMarkerWEST setMarkerText "HQ is destroyed";
					};
				};

				case 5:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "MEDEVAC";
					} else {
						_nameMarkerWEST setMarkerText "MEDEVAC is destroyed";
					};
				};

			};
		};

		case 2:
		{
			switch (_text) do {

				case 1:
				{
					if (alive _unit) then {
						_nameMarkerEAST setMarkerPos (getPosVisual _unit);
						_nameMarkerEAST setMarkerText "Repair truck";
					} else {
						_nameMarkerEAST setMarkerText "Repair truck is destroyed";
					};
				};

				case 2:
				{
					if (alive _unit) then {
						_nameMarkerEAST setMarkerPos (getPosVisual _unit);
						_nameMarkerEAST setMarkerText "Fuel truck";
					} else {
						_nameMarkerEAST setMarkerText "Fuel truck is destroyed";
					};
				};

				case 3:
				{
					if (alive _unit) then {
						_nameMarkerEAST setMarkerPos (getPosVisual _unit);
						_nameMarkerEAST setMarkerText "Ammo truck";
					} else {
						_nameMarkerEAST setMarkerText "Ammo truck is destroyed";
					};
				};

				case 4:
				{
					if (alive _unit) then {
						_nameMarkerEAST setMarkerPos (getPosVisual _unit);
						_nameMarkerEAST setMarkerText "HQ";
					} else {
						_nameMarkerEAST setMarkerText "HQ is destroyed";
					};
				};

				case 5:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "MEDEVAC";
					} else {
						_nameMarkerWEST setMarkerText "MEDEVAC is destroyed";
					};
				};

			};
		};

		case 3:
		{
			switch (_text) do {

				case 1:
				{
					if (alive _unit) then {
						_nameMarkerIND setMarkerPos (getPosVisual _unit);
						_nameMarkerIND setMarkerText "Repair truck";
					} else {
						_nameMarkerIND setMarkerText "Repair truck is destroyed";
					};
				};

				case 2:
				{
					if (alive _unit) then {
						_nameMarkerIND setMarkerPos (getPosVisual _unit);
						_nameMarkerIND setMarkerText "Fuel truck";
					} else {
						_nameMarkerIND setMarkerText "Fuel truck is destroyed";
					};
				};

				case 3:
				{
					if (alive _unit) then {
						_nameMarkerIND setMarkerPos (getPosVisual _unit);
						_nameMarkerIND setMarkerText "Ammo truck";
					} else {
						_nameMarkerIND setMarkerText "Ammo truck is destroyed";
					};
				};

				case 4:
				{
					if (alive _unit) then {
						_nameMarkerIND setMarkerPos (getPosVisual _unit);
						_nameMarkerIND setMarkerText "HQ";
					} else {
						_nameMarkerIND setMarkerText "HQ is destroyed";
					};
				};

				case 5:
				{
					if (alive _unit) then {
						_nameMarkerWEST setMarkerPos (getPosVisual _unit);
						_nameMarkerWEST setMarkerText "MEDEVAC";
					} else {
						_nameMarkerWEST setMarkerText "MEDEVAC is destroyed";
					};
				};

			};
		};
	};

	sleep 5;
};

 

scripts\Vehicle.sqf ( Vehicle respawn script )
 

Spoiler

/*  
==================================================================================================================
  Simple Vehicle Respawn Script v1.81 for Arma 3
  by Tophe of Östgöta Ops [OOPS] and tweaked for I&A 3 by Rarek [AW]
  
  Put this in the vehicles init line:
  veh = [this] execVM "vehicle.sqf"

  
  Options:
  There are some optional settings. The format for these are:
  veh = [object, Delay, Deserted timer, Respawns, Effect, Dynamic] execVM "vehicle.sqf"
  
  Default respawn delay is 30 seconds, to set a custom respawn delay time, put that in the init as well. 
  Like this:
  veh = [this, 15] execVM "vehicle.sqf"

  Default respawn time when vehicle is deserted, but not destroyed is 120 seconds. To set a custom timer for this 
  first set respawn delay, then the deserted vehicle timer. (0 = disabled) 
  Like this:  
  veh = [this, 15, 10] execVM "vehicle.sqf"

  By default the number of respawns is infinite. To set a limit first set preceding values then the number of respawns you want (0 = infinite).
  Like this:
  veh = [this, 15, 10, 5] execVM "vehicle.sqf"

  Set this value to TRUE to add a special explosion effect to the wreck when respawning.
  Default value is FALSE, which will simply have the wreck disappear.
  Like this:
  veh = [this, 15, 10, 5, TRUE] execVM "vehicle.sqf"
  
  By default the vehicle will respawn to the point where it first was when the mission started (static). 
  This can be changed to dynamic. Then the vehicle will respawn to the position where it was destroyed. 
  First set all preceding values then set TRUE for dynamic or FALSE for static.
  Like this:
  veh = [this, 15, 10, 5, TRUE, TRUE] execVM "vehicle.sqf"
  
  If you you want to set the INIT field of the respawned vehicle, first set all other values, then set init commands. 
  Those must be inside quotations.
  Like this:
  veh = [this, 15, 10, 5, TRUE, FALSE, "this setDammage 0.5"] execVM "vehicle.sqf"		
  
  Default values of all settings are:
  veh = [this, 30, 120, 0, FALSE, FALSE] execVM "vehicle.sqf"
  
	
Contact & Bugreport: cwadensten@gmail.com
================================================================================================================== */
  
if (!isServer) exitWith {};

// Define variables
_unit = [_this,0,objNull,[objNull]] call BIS_fnc_param;
_delay = [_this,1,30,[0]] call BIS_fnc_param;
_deserted = [_this,2,120,[0]] call BIS_fnc_param;
_respawns = [_this,3,0,[0]] call BIS_fnc_param;
_explode = [_this,4,false,[true]] call BIS_fnc_param;
_dynamic = [_this,5,false,[true]] call BIS_fnc_param;
_unitinit = [_this,6];
_haveinit = if (count _this > 6) then { true } else { false };

_hasname = false;
_unitname = vehicleVarName _unit;
if (isNil _unitname) then {_hasname = false;} else {_hasname = true;};
_noend = true;
_run = true;
_rounds = 0;

if (_delay < 0) then {_delay = 0};
if (_deserted < 0) then {_deserted = 0};
if (_respawns <= 0) then {_respawns= 0; _noend = true;};
if (_respawns > 0) then {_noend = false};

_dir = getDir _unit;
_position = getPosASL _unit;
_type = typeOf _unit;
_dead = false;
_nodelay = false;

// Start monitoring the vehicle
while {_run} do 
{	
	sleep (2 + random 10);
	if ((getDammage _unit > 0.8) and ({alive _x} count crew _unit == 0)) then {_dead = true};

	// Check if the vehicle is deserted.
	if (_deserted > 0) then
	{
		if ((getPosASL _unit distance _position > 10) and ({alive _x} count crew _unit == 0) and (getDammage _unit < 0.8)) then 
		{
			_timeout = time + _deserted;
			sleep 0.1;
			waitUntil {_timeout < time or !alive _unit or {alive _x} count crew _unit > 0};

			if ({alive _x} count crew _unit > 0) then {_dead = false}; 
			if ({alive _x} count crew _unit == 0) then {_dead = true; _nodelay =true}; 
			if !(alive _unit) then {_dead = true; _nodelay = false}; 
		};
	};

	// Respawn vehicle
	if (_dead) then 
	{	
		if (_nodelay) then {sleep 0.1; _nodelay = false;} else {sleep _delay;};
		if (_dynamic) then {_position = getPosASL _unit; _dir = getDir _unit;};
		if (_explode) then {_effect = "M_AT" createVehicle getPosASL _unit; _effect setPosASL getPosASL _unit;};
		sleep 0.1;

		deleteVehicle _unit;
		sleep 2;
		_unit = _type createVehicle _position;
		_unit setPosASL _position;
		_unit setDir _dir;
		if (["B_UAV", _type] call BIS_fnc_inString) then { createVehicleCrew _unit; };

		if (_haveinit) then 
		{
			_unit call compile format ["%1=_This; PublicVariable '%1'",_unitinit];
		};

		if (_hasname) then 
		{
			_unit setVehicleVarName _unitname;
			_unit call compile format ["%1=_This; PublicVariable '%1'",_unitname];
		};	
		_dead = false;

		// Check respawn amount
		if !(_noend) then {_rounds = _rounds + 1};
		if ((_rounds == _respawns) and !(_noend)) then {_run = false;};
	};
};

 

Edited by Dedmen
Code moved into spoiler tag

Share this post


Link to post
Share on other sites
6 hours ago, HonzaVinCZ said:

Problem with this script is, that it cannot find target vehicle after vehicle was destroyed and respawned by other script

You need to reference your vehicles via their vehicleVarName.

//Get vehicles vehicleVarName OR create one if it does not have one
_vehicleVarName = [ _vehicle ] call BIS_fnc_objectVar;

Then use _vehicleVarName as a reference to the vehicle in the update loop.

_vehicle = missionNamespace getVariable[ _vehicleVarName, objNull ];

If _vehicle is objNull then ignore it. It either does not exist or is currently destroyed and awaiting respawning.

 

Tophe's respawn script already looks if the vehicle has a vehicleVarName and applies it to the respawned vehicle.

if (_hasname) then 
{
  _unit setVehicleVarName _unitname;
  _unit call compile format ["%1=_This; PublicVariable '%1'",_unitname];
};	

You just need to make sure the vehicle has had its vehicleVarName applied before Tophe's respawn script is run so that it recognises it has a name during initialisation of the respawn scriipt.

 

Maybe something like...

Spoiler

// [ vehicle, type, side ] execVM "scripts\VehicleMarkers.sqf";

// vehicle - object
// type - one of, Repair, Fuel, Ammo, MHQ, MEDEVAC
// side - east, west, independent

//EXAMPLE for vehicle init
// [ this, "Fuel", west ] execVM "scripts\VehicleMarkers.sqf";

//To remove a vehicles marker
// [ vehicle, true ] execVM "scripts\VehicleMarkers.sqf";


//If an invalid argument type is given OR default used
if !( params[
	[ "_vehicle", objNull, [ objNull ] ],
	[ "_type", "", [ "", true ] ]
] ) exitWith {
	//Exit with error
	format[ "Invalid argument: Veh: %1, Type: %2", _vehicle, _type ] call BIS_fnc_error;
};

//If type is a bool
if ( _type isEqualType true ) exitWith {
	//And we have initiated markers update array
	if !( isNil "TAG_vehicleMarkers" ) then {
		//Find the passed vehicles var in markers update array
		_index = TAG_vehicleMarkers findIf{ _x select 0 isEqualTo ( _vehicle call BIS_fnc_objectVar ) };
		//If we found it
		if ( _index > -1 ) then {
			//Delete marker
			deleteMarkerLocal ( TAG_vehicleMarkers select _index select 1 );
			//And flag index in update array for removal
			TAG_vehicleMarkers set[ _index, objNull ];
		};
	};
};

//If an invalid type for _side is given OR default used
if !( _this select 2 params[
	[ "_side", sideUnknown, [ sideUnknown ] ]
] ) exitWith {
	//Exit with error
	format[ "Invalid Side: %1", _side ] call BIS_fnc_error;
};

//If we have not passed a valid marker type
if !( toUpper _type in [ "REPAIR", "FUEL", "AMMO", "MHQ", "MEDEVAC" ] ) exitWith {
	//Exit with error
	format[ "Invalid marker type: %1", _type ] call BIS_fnc_error;
};

//If we have passed an unsuported side
if !( _side in [ east, west, independent ] ) exitWith {
	//Exit with error
	format[ "Unsupported side given: %1", _side ] call BIS_fnc_error;
};

//Dont want to create a marker if the player is never going to see it
//Exit silently
if !( playerSide isEqualTo _side ) exitWith {};

//Get OR create a vehicleVarName for the vehicle
_vehicleVar = [ _vehicle ] call BIS_fnc_objectVar;

//Create a name for the marker based on counter
_markerName = format[ "vehicleMarker_%1", [ "VehicleMarker", 1 ] call BIS_fnc_counter ];

//Find the marker type asked for
switch ( toUpper _type ) do {
	case "REPAIR" : {
		[ "b_unknown", "Repair truck" ]
	};
	case "FUEL" : {
		[ "b_unknown", "Fuel truck" ]
	};
	case "AMMO" : {
		[ "b_unknown", "Ammo truck" ]
	};
	case "MHQ" : {
		[ "b_hq", "HQ" ]
	};
	case "MEDEVAC" : {
		[ "b_med", "MEDEVAC" ]
	};
	//Pass out marker icon type and default marker text
} params[ "_markerType", "_markerText" ];

//Create marker locally
_marker = createMarkerLocal [ _markerName, getPosVisual _vehicle ];
_marker setMarkerShapeLocal "ICON";
_marker setMarkerTypeLocal _markerType;
_marker setMarkerColorLocal ( [ "colorEAST", "colorWEST", "colorGUER" ] select ( _side call BIS_fnc_sideID ));
_marker setMarkerTextLocal _markerText;

//If the vehicle marker EH has not been started
if ( isNil "TAG_vehicleMarkers_EH" ) then {
	//Initiate marker update array with this markers info
	TAG_vehicleMarkers = [ [ _vehicleVar, _marker, _markerText ] ];
	//Add marker update EH
	TAG_vehicleMarkers_EH = addMissionEventHandler [ "EachFrame", {
		//For each vehicle markers
		{
			_x params[ "_vehicleVar", "_marker", "_markerText" ];
    	
			//If vehicleVar is of type objNull
			if ( _vehicleVar isEqualType objNull ) then {
				//Then it has been flagged for removal
				//Delete it from the update array
				private _nul = TAG_vehicleMarkers deleteAt _forEachIndex;
			}else{
				//Only update markers if map or gps is open
				if ( visibleMap || visibleGPS ) then {
					//Get vehicle via its vehicleVarName
					//This is how to catch respawning vehicles. As long as the vehicle is respawned
					//with the old vehicles vehcileVarName
					//Then the marker will be associated with the respawned vehicle
					_vehicle = missionNamespace getVariable[ _vehicleVar, objNull ];
    	        	
					//If we found the vehicle
					if ( !isNull _vehicle ) then {
						//Update marker position
						_marker setMarkerPosLocal getPosVisual _vehicle;
						//If the vehicle is dead
						if ( !alive _vehicle ) then {
							//And its marker is still the default text
							if ( markerText _marker == _markerText ) then {
								//Update marker text to destroyed
								_marker setMarkerTextLocal format[ "%1 is destroyed", _markerText ];
							};
						}else{
							//Its ALIVE!!
							//If the marker text is not default
							if !( markerText _marker == _markerText ) then {
								//Set marker text to default
								_marker setMarkerTextLocal _markerText;
							};
						};
					};
				};
			};
			//Only iterate on a copy of the vehicle markers update array ( + )
			//This makes it safe to delete indexes from the array whilst iterating over the copy
		}forEach +TAG_vehicleMarkers;
		
		//If there are no markers left in the update array
		if ( TAG_vehicleMarkers isEqualTo [] ) then {
			//Reset markers array
			TAG_vehicleMarkers = nil;
			//Reset EH handle
			TAG_vehicleMarkers_EH = nil;
			//Remove this EH
			removeMissionEventHandler[ "EachFrame", _thisEventHandler ];
		};
	}];
}else{
	//Otherwise EH is already running
	//Just add vehicle marker info to the update array
	private _nul = TAG_vehicleMarkers pushBackUnique [ _vehicleVar, _marker, _markerText ];
};

 

 

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites
11 hours ago, HonzaVinCZ said:

_unit call compile format ["%1=_This; PublicVariable '%1'",_unitname];

Oh gosh. Please never do that.
That is just a worse to read, and much worse in performance variant of

_missionNamespace setVariable [_unitname, _unit, true];

Somehow I see such bad code over and over again recently.

 

4 hours ago, Larrow said:

private _nul =

No reason to put something into a variable that you never intend on using.

 

Wow I don't think I've ever seen such good error checking and notification in a script before. Nice work.

  • Like 3

Share this post


Link to post
Share on other sites
5 hours ago, Larrow said:

You need to reference your vehicles via their vehicleVarName.


//Get vehicles vehicleVarName OR create one if it does not have one
_vehicleVarName = [ _vehicle ] call BIS_fnc_objectVar;

Then use _vehicleVarName as a reference to the vehicle in the update loop.


_vehicle = missionNamespace getVariable[ _vehicleVarName, objNull ];

If _vehicle is objNull then ignore it. It either does not exist or is currently destroyed and awaiting respawning.

 

Tophe's respawn script already looks if the vehicle has a vehicleVarName and applies it to the respawned vehicle.


if (_hasname) then 
{
  _unit setVehicleVarName _unitname;
  _unit call compile format ["%1=_This; PublicVariable '%1'",_unitname];
};	

You just need to make sure the vehicle has had its vehicleVarName applied before Tophe's respawn script is run so that it recognises it has a name during initialisation of the respawn scriipt.

 

Maybe something like...

  Reveal hidden contents


// [ vehicle, type, side ] execVM "scripts\VehicleMarkers.sqf";

// vehicle - object
// type - one of, Repair, Fuel, Ammo, MHQ, MEDEVAC
// side - east, west, independent

//EXAMPLE for vehicle init
// [ this, "Fuel", west ] execVM "scripts\VehicleMarkers.sqf";

//To remove a vehicles marker
// [ vehicle, true ] execVM "scripts\VehicleMarkers.sqf";


//If an invalid argument type is given OR default used
if !( params[
	[ "_vehicle", objNull, [ objNull ] ],
	[ "_type", "", [ "", true ] ]
] ) exitWith {
	//Exit with error
	format[ "Invalid argument: Veh: %1, Type: %2", _vehicle, _type ] call BIS_fnc_error;
};

//If type is a bool
if ( _type isEqualType true ) exitWith {
	//And we have initiated markers update array
	if !( isNil "TAG_vehicleMarkers" ) then {
		//Find the passed vehicles var in markers update array
		_index = TAG_vehicleMarkers findIf{ _x select 0 isEqualTo ( _vehicle call BIS_fnc_objectVar ) };
		//If we found it
		if ( _index > -1 ) then {
			//Delete marker
			deleteMarkerLocal ( TAG_vehicleMarkers select _index select 1 );
			//And flag index in update array for removal
			TAG_vehicleMarkers set[ _index, objNull ];
		};
	};
};

//If an invalid type for _side is given OR default used
if !( _this select 2 params[
	[ "_side", sideUnknown, [ sideUnknown ] ]
] ) exitWith {
	//Exit with error
	format[ "Invalid Side: %1", _side ] call BIS_fnc_error;
};

//If we have not passed a valid marker type
if !( toUpper _type in [ "REPAIR", "FUEL", "AMMO", "MHQ", "MEDEVAC" ] ) exitWith {
	//Exit with error
	format[ "Invalid marker type: %1", _type ] call BIS_fnc_error;
};

//If we have passed an unsuported side
if !( _side in [ east, west, independent ] ) exitWith {
	//Exit with error
	format[ "Unsupported side given: %1", _side ] call BIS_fnc_error;
};

//Dont want to create a marker if the player is never going to see it
//Exit silently
if !( playerSide isEqualTo _side ) exitWith {};

//Get OR create a vehicleVarName for the vehicle
_vehicleVar = [ _vehicle ] call BIS_fnc_objectVar;

//Create a name for the marker based on counter
_markerName = format[ "vehicleMarker_%1", [ "VehicleMarker", 1 ] call BIS_fnc_counter ];

//Find the marker type asked for
switch ( toUpper _type ) do {
	case "REPAIR" : {
		[ "b_unknown", "Repair truck" ]
	};
	case "FUEL" : {
		[ "b_unknown", "Fuel truck" ]
	};
	case "AMMO" : {
		[ "b_unknown", "Ammo truck" ]
	};
	case "MHQ" : {
		[ "b_hq", "HQ" ]
	};
	case "MEDEVAC" : {
		[ "b_med", "MEDEVAC" ]
	};
	//Pass out marker icon type and default marker text
} params[ "_markerType", "_markerText" ];

//Create marker locally
_marker = createMarkerLocal [ _markerName, getPosVisual _vehicle ];
_marker setMarkerShapeLocal "ICON";
_marker setMarkerTypeLocal _markerType;
_marker setMarkerColorLocal ( [ "colorEAST", "colorWEST", "colorGUER" ] select ( _side call BIS_fnc_sideID ));
_marker setMarkerTextLocal _markerText;

//If the vehicle marker EH has not been started
if ( isNil "TAG_vehicleMarkers_EH" ) then {
	//Initiate marker update array with this markers info
	TAG_vehicleMarkers = [ [ _vehicleVar, _marker, _markerText ] ];
	//Add marker update EH
	TAG_vehicleMarkers_EH = addMissionEventHandler [ "EachFrame", {
		//For each vehicle markers
		{
			_x params[ "_vehicleVar", "_marker", "_markerText" ];
    	
			//If vehicleVar is of type objNull
			if ( _vehicleVar isEqualType objNull ) then {
				//Then it has been flagged for removal
				//Delete it from the update array
				private _nul = TAG_vehicleMarkers deleteAt _forEachIndex;
			}else{
				//Only update markers if map or gps is open
				if ( visibleMap || visibleGPS ) then {
					//Get vehicle via its vehicleVarName
					//This is how to catch respawning vehicles. As long as the vehicle is respawned
					//with the old vehicles vehcileVarName
					//Then the marker will be associated with the respawned vehicle
					_vehicle = missionNamespace getVariable[ _vehicleVar, objNull ];
    	        	
					//If we found the vehicle
					if ( !isNull _vehicle ) then {
						//Update marker position
						_marker setMarkerPosLocal getPosVisual _vehicle;
						//If the vehicle is dead
						if ( !alive _vehicle ) then {
							//And its marker is still the default text
							if ( markerText _marker == _markerText ) then {
								//Update marker text to destroyed
								_marker setMarkerTextLocal format[ "%1 is destroyed", _markerText ];
							};
						}else{
							//Its ALIVE!!
							//If the marker text is not default
							if !( markerText _marker == _markerText ) then {
								//Set marker text to default
								_marker setMarkerTextLocal _markerText;
							};
						};
					};
				};
			};
			//Only iterate on a copy of the vehicle markers update array ( + )
			//This makes it safe to delete indexes from the array whilst iterating over the copy
		}forEach +TAG_vehicleMarkers;
		
		//If there are no markers left in the update array
		if ( TAG_vehicleMarkers isEqualTo [] ) then {
			//Reset markers array
			TAG_vehicleMarkers = nil;
			//Reset EH handle
			TAG_vehicleMarkers_EH = nil;
			//Remove this EH
			removeMissionEventHandler[ "EachFrame", _thisEventHandler ];
		};
	}];
}else{
	//Otherwise EH is already running
	//Just add vehicle marker info to the update array
	private _nul = TAG_vehicleMarkers pushBackUnique [ _vehicleVar, _marker, _markerText ];
};

 

 

That is just perfect! Thank you a lot! 

 

 

16 minutes ago, Dedmen said:

Oh gosh. Please never do that.
That is just a worse to read, and much worse in performance variant of


_missionNamespace setVariable [_unitname, _unit, true];

 

Oh yes, I'm still beginner in scripting so I know about it little. I can create something that works but I have no idea what it could do with performance. Also I'm basically learning C++ in Arma engine and that's also not ideal but I actually don't use C++ anywhere else.

Share this post


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

No reason to put something into a variable that you never intend on using.

I always try to swallow unneeded values. Had it bite me in the arse plenty of times. Case in point if I didn't swallow that last statement in the script then the function could return an integer( pushed index ) and that is not intended. Yes I realise the example is execVM but you never know where your code is going to end up (if someone turns it into a registered function and calls it instead). Maybe I should employ always returning true but again why if not intended feature.

 

1 hour ago, Dedmen said:

Oh gosh. Please never do that.
That is just a worse to read, and much worse in performance variant of


_missionNamespace setVariable [_unitname, _unit, true];

Somehow I see such bad code over and over again recently. 

Got to remember Tophe's script has been around for along time, long before setVariable was able to public variable on anything but object namespace (missionNamespace PV has only been available since 1.48). Theres lots of things in old code that look terrible now 😃

  • Like 1

Share this post


Link to post
Share on other sites
4 hours ago, Larrow said:

then the function could return an integer

Actually the "swallowing" at the end that you are doing is VERY terrible. As you are hitting the only bug in the SQF language.

 

Variable assignment returns nothing, not even nil. Just nothing at all.
If you then try to assign nothing to a variable you cause an error.

 

MyFunc = {
_nul = doStuff;
};

_nul = call MyFunc; //ERROR! MyFunc didn't return anything, there is nothing left on the stack that I can assign here!

 

You should NEVER ever return nothing/an assignment. Atleast return a nil if you really want it not to return something else.
So instead of returning a "unintended" value, you are currently breaking every script that calls your function and for whatever reason tries to store the returned value.

 

See https://community.bistudio.com/wiki/a_%3D_b (basically just repeat of what I just said)

 

The only place where you would ever do that, is in init boxes in the editor, because they are bugged, and you can workaround their bug by using the other bug.

This is still Arma afterall right? (Btw you don't need x=stuff in editor at all if you are running CBA. As CBA itself has a fix for that bug)

  • Like 1

Share this post


Link to post
Share on other sites

Thanks good to know.

 

23 minutes ago, Dedmen said:

you are currently breaking every script that calls your function and for whatever reason tries to store the returned value

Thats user error on behalf of user expecting something back. /jk 😄

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

×