Jump to content
Sign in to follow this  
heinzmcdurgen

Marker on map approx where player is located

Recommended Posts

I'm working on a mission where players are trying to hunt down a sniper. I'd like for the location of the sniper to be approximately known after he fires and then gets smaller the more he fires, but fades with time.

For example, Sniper fires. A map marker with a 500m radius pops up. The sniper is somewhere (anywhere, not the middle) of the marker. If he fires again within X seconds the map marker shrinks to a 250m radius, again a 100m radius, etc. If he doesn't fire for Y seconds the marker fades into nothing until he fires again - at which time it would be a 500m radius again.

Does anyone have an idea of how to do this?

Thanks!

Share this post


Link to post
Share on other sites

Well, I'm kinda tired, and the following may or may not work the exact way you want (or might not work at all) and probably isn't the best solution, but it's worth a shot :). Replace the "#" where you see "timeX = #;" with the time you want it to wait before the marker is deleted. Either apply this to the sniper via whatever script spawns him, or put it in the init field of the sniper replacing "_sniper" with "this" instead.

_sniper addEventHandler
[
"Fired",
{
	_loop = [(_this select 0)] spawn
	{
		_unit = (_this select 0);
		_timeX = #;

		if (isNil "glb_shotFiredBySniper") then
		{
			glb_shotFiredBySniper = 0;
			publicVariable "glb_shotFiredBySniper";
		};

		if (markerPos "radiusMarkerOnSniper" isEqualTo [0,0,0]) then
		{
			_mrk = createMarker [
									"radiusMarkerOnSniper",
									[
										((getPos _unit select 0) + (random(25)+50)),
										((getPos _unit select 1) + (random(25)+50)),
										(getPos _unit select 2)
									]
								];
			_mrk setMarkerShape "ELLIPSE";
			_mrk setMarkerSize [500,500];
			_mrk setMarkerColor "ColorRed";

			_deleteMarkerAfterTimeX = [_mrk,_timeX] spawn
			{
				_sleepSpawn = [(_this select 1)] spawn
				{
					sleep (_this select 0);
				};

				waitUntil {scriptDone _sleepSpawn || glb_shotFiredBySniper isEqualTo (glb_shotFiredBySniper + 1)};

				if (scriptDone _sleepSpawn) then
				{
					for "_i" from 1 to 0 step -0.2 do
					{
						(_this select 0) setMarkerAlpha _i;
						sleep 1;
					};
					deleteMarker (_this select 0);
				}
				else
				{
					terminate _sleepSpawn;
				};
			};
		}
		else
		{
			_mrk = "radiusMarkerOnSniper";

			glb_shotFiredBySniper = glb_shotFiredBySniper + 1;
			publicVariable "glb_shotFiredBySniper";

			switch ((getMarkerSize _mrk) select 0) do
			{
				case 500: 
				{
					_mrk setMarkerSize [250,250];
					_mrk setMarkerPos 
					[
						((getPos _unit select 0) + (random(25)+25)),
						((getPos _unit select 1) + (random(25)+25)),
						(getPos _unit select 2)
					];
					_mrk setMarkerAlpha 1;
				};
				case 250: 
				{
					_mrk setMarkerSize [100,100];
					_mrk setMarkerPos 
					[
						((getPos _unit select 0) + (random(25)+10)),
						((getPos _unit select 1) + (random(25)+10)),
						(getPos _unit select 2)
					];
					_mrk setMarkerAlpha 1;
				};
				case 100: 
				{
					_mrk setMarkerSize [50,50];
					_mrk setMarkerPos 
					[
						((getPos _unit select 0) + (random(10)+10)),
						((getPos _unit select 1) + (random(10)+10)),
						(getPos _unit select 2)
					];
					_mrk setMarkerAlpha 1;
				};
				default {};
			};
		};
	};
}
];

EDIT: Did quick test on isNil on a non-existing marker, and doesn't give desired result, changed to new method above.

EDIT2: Couple more changes as I keep thinking :p.

EDIT3: Added fade effect after seeing Larrow's code, and realizing I forgot to put it in, FYI never code when tired :D.

Edited by JShock

Share this post


Link to post
Share on other sites

Heres something similar that i had written for highest bounty game mode. I have mashed it down into one EH for ease of posting as it had alot of extra stuff involved passing more than just markers across the network.

I see JShock has already posted something similar while i was rewritting mine,

player addEventHandler [ "Fired", {
_unit = _this select 0;

_SHOT_TIMEOUT = 20;
_MRK_RADIUS = [ 500, 250, 125, 60, 4 ];

_lastShot = _unit getVariable [ "fired_time", nil ];

if !( isNil "_lastShot" ) then {

	if ( time < (( _lastShot select 0 ) + _SHOT_TIMEOUT ) ) then {
		_lastshot set [ 0, time ];
		_lastshot set [ 1, (( _lastshot select 1 ) + 1 ) min (( count _MRK_RADIUS ) - 1 ) ];
	}else{
		_lastshot = [ time, 0 ];
	};

}else{
	_lastshot = [ time, 0 ];
};

_unit setVariable [ "fired_time", _lastshot ];

_mrkName = format[ "shotMarker_%1", name _unit ];
_mrkSize = _MRK_RADIUS select ( _lastshot select 1 );
_pos = [ _unit, random _mrkSize, random 360 ] call BIS_fnc_relPos;

if !( isNil "mrkAlphaThread" ) then {
	terminate mrkAlphaThread;
	_mrkName setMarkerPos _pos;
	_mrkName setMarkerAlpha 1;
}else{
	_mrk = createMarker [ _mrkName, _pos ];
	_mrk setMarkerColor "colorRed";
	_mrk setMarkerShape "ELLIPSE";
};

_mrkName setMarkerSize [ _mrkSize, _mrkSize ];

mrkAlphaThread = _mrkName spawn {
	for "_alpha" from 1 to 0 step -0.1 do {
		_this setMarkerAlpha _alpha;
		sleep 2;
	};
	deleteMarker _this;
	mrkAlphaThread = nil;
};

}];

EDIT: Although the above works, you would be better off letting each client handle its own marker/alpha rather than spamming alpha changes across the network. Just thought i would make that clear after ive crunched it into one EH for an example.

Edited by Larrow

Share this post


Link to post
Share on other sites
I see JShock has already posted something similar while i was rewritting mine,

Yep, but my version is definitely overly simplified to what he is after, yours is more to the point :p.

Share this post


Link to post
Share on other sites

Hello, this should do everything you have asked for. Put it in the init of the sniper:

if (isServer) then
{
this addEventHandler ["fired",
{
	_firedAgain = 10;

	_unit = (_this select 0);
	_last = _unit getVariable ["time_last_fired",0];
	_unit setVariable ["time_last_fired", time];

	if ((time - _last) < _firedAgain) then
	{
		terminate (_unit getVariable ["fired_script", nil]);
		deleteMarker (name _unit);
		_unit setVariable ["marker_precision", (_unit getVariable ["marker_precision", 3]) - 1];
		if (_unit getVariable "marker_precision" <= 0) then
		{
			_unit setVariable ["marker_precision", 0];
		};
		_precision = [100,250,500] select (_unit getVariable ["marker_precision", 2]);
		_marker = createMarker [name _unit, [_unit, _precision - (floor(random _precision)), floor (random 360)] call BIS_fnc_relPos];
		_marker setMarkerShape "ELLIPSE";
		_marker setMarkerSize [_precision,_precision];
		_packet = [[[_marker, _firedAgain],
		{
			if (!isNil "fired_handler") then
			{
				terminate fired_handler;
			};
			fired_handler = _this spawn
			{
				uiSleep (_this select 1);
				while {markerAlpha (_this select 0) > 0} do
				{
					(_this select 0) setMarkerAlpha ((markerAlpha (_this select 0)) - 0.000001);
				};
			}
		}], "BIS_fnc_spawn", true, false, false] call BIS_fnc_MP;
	}else
	{
		_unit setVariable ["marker_precision", nil];
	};
}];
};

(44 lines)

Share this post


Link to post
Share on other sites
EDIT: Although the above works, you would be better off letting each client handle its own marker/alpha rather than spamming alpha changes across the network. Just thought i would make that clear after ive crunched it into one EH for an example.

How would I go about doing this?

This community never ceases to amaze me. Thanks for all your help guys.

Share this post


Link to post
Share on other sites

I believe this should give you the desired effect (iteration of Larrow's example):

Ok, here we go, I had assumed that setMarkerAlphaLocal was remotely executable, checked, and was wrong, but fixed below :):

player addEventHandler [ "Fired", {
   _unit = _this select 0;

   _SHOT_TIMEOUT = 20;
   _MRK_RADIUS = [ 500, 250, 125, 60, 4 ];

   _lastShot = _unit getVariable [ "fired_time", nil ];

   if !( isNil "_lastShot" ) then {

       if ( time < (( _lastShot select 0 ) + _SHOT_TIMEOUT ) ) then {
           _lastshot set [ 0, time ];
           _lastshot set [ 1, (( _lastshot select 1 ) + 1 ) min (( count _MRK_RADIUS ) - 1 ) ];
       }else{
           _lastshot = [ time, 0 ];
       };

   }else{
       _lastshot = [ time, 0 ];
   };

   _unit setVariable [ "fired_time", _lastshot ];

   _mrkName = format[ "shotMarker_%1", name _unit ];
   _mrkSize = _MRK_RADIUS select ( _lastshot select 1 );
   _pos = [ _unit, random _mrkSize, random 360 ] call BIS_fnc_relPos;

   if !( isNil "mrkAlphaThread" ) then {
       terminate mrkAlphaThread;
       _mrkName setMarkerPos _pos;
	[[[_mrkName,1],{(_this select 0) setMarkerAlphaLocal (_this select 1)}],"BIS_fnc_call",true,false,false] call BIS_fnc_MP;
   }else{
       _mrk = createMarker [ _mrkName, _pos ];
       _mrk setMarkerColor "colorRed";
       _mrk setMarkerShape "ELLIPSE";
   };

   _mrkName setMarkerSize [ _mrkSize, _mrkSize ];

   mrkAlphaThread = _mrkName spawn {
       for "_alpha" from 1 to 0 step -0.1 do {
           [[[_this,_alpha],{(_this select 0) setMarkerAlphaLocal (_this select 1)}],"BIS_fnc_call",true,false,false] call BIS_fnc_MP;
           sleep 2;
       };
       deleteMarker _this;
       mrkAlphaThread = nil;
   };

}];  

Edited by JShock

Share this post


Link to post
Share on other sites
My version already did that

But your still using the "setMarkerAlpha" command, which is effects global, so you are correct in using BIS_fnc_MP to execute on all clients, however, AFAIK you are now executing a globalized command on each client, for every other client, so that's why I used "setMarkerAlphaLocal", that way it's executing on each client, but only to the client themselves, which I believe is what Larrow was referring to.

Share this post


Link to post
Share on other sites

init.sqf

MRK_RADIUS = [ 500, 250, 125, 60, 4 ];

if ( isServer ) then {

sniper addEventHandler [ "Fired", {
	_unit = _this select 0;

	_SHOT_TIMEOUT = 20;

	_lastShot = _unit getVariable [ "fired_time", nil ];

	if !( isNil "_lastShot" ) then {

		if ( time < (( _lastShot select 0 ) + _SHOT_TIMEOUT ) ) then {
			_lastshot set [ 0, time ];
			_lastshot set [ 1, (( _lastshot select 1 ) + 1 ) min (( count MRK_RADIUS ) - 1 ) ];
		}else{
			_lastshot = [ time, 0 ];
		};

	}else{
		_lastshot = [ time, 0 ];
	};

	_unit setVariable [ "fired_time", _lastshot ];

	[ [ _unit, _lastshot select 1 ], "fnc_createShotMarker", true ]	call BIS_fnc_MP;

}];
};

if ( !isDedicated ) then {

fnc_createShotMarker = {

	_unit = _this select 0;
	_shotCount = _this select 1;

	_mrkName = format[ "shotMarker_%1", name _unit ];
	_mrkSize = MRK_RADIUS select _shotCount;
	_pos = [ _unit, random _mrkSize, random 360 ] call BIS_fnc_relPos;
	if !( isNil "mrkAlphaThread" ) then {
		terminate mrkAlphaThread;
		_mrkName setMarkerPosLocal _pos;
		_mrkName setMarkerAlphaLocal 1;
	}else{
		_mrk = createMarkerLocal [ _mrkName, _pos ];
		_mrk setMarkerColorLocal "colorRed";
		_mrk setMarkerShapeLocal "ELLIPSE";
	};

	_mrkName setMarkerSizeLocal [ _mrkSize, _mrkSize ];

	mrkAlphaThread = _mrkName spawn {
		for "_alpha" from 1 to 0 step -0.1 do {
		    _this setMarkerAlphaLocal _alpha;
		    sleep 2;
		};
		deleteMarkerLocal _this;
		mrkAlphaThread = nil;
	};
};
};

Where sniper is the name given to your sniper in the editor

But your still using the "setMarkerAlpha" command, which is effects global, so you are correct in using BIS_fnc_MP to execute on all clients, however, AFAIK you are now executing a globalized command on each client,
Yes this is kind of what i was getting at. Even though your using BIS_fnc_MP DE its still sending a network message for every alpha change. Jshock your rewrite still has the problem even though your using BIS_fnc_MP and alphaLocal, it is still sending a network message for each change.

The above hands of marker creation and alpha changes to each client, it is then their responsibility to handle alpha changes. There is only ever one network message sent when ever a new shot is fired.

Share this post


Link to post
Share on other sites

Makes sense, I was so focused on locality of the commands and such I didn't think about the network traffic as much as I should have :p.

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
Sign in to follow this  

×