heinzmcdurgen 10 Posted February 20, 2015 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
jshock 513 Posted February 20, 2015 (edited) 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 February 20, 2015 by JShock Share this post Link to post Share on other sites
Larrow 2822 Posted February 20, 2015 (edited) 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 February 20, 2015 by Larrow Share this post Link to post Share on other sites
jshock 513 Posted February 20, 2015 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
dreadedentity 278 Posted February 20, 2015 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
heinzmcdurgen 10 Posted February 20, 2015 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
jshock 513 Posted February 20, 2015 (edited) 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 February 20, 2015 by JShock Share this post Link to post Share on other sites
dreadedentity 278 Posted February 20, 2015 How would I go about doing this? My version already did that Share this post Link to post Share on other sites
jshock 513 Posted February 20, 2015 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
Larrow 2822 Posted February 20, 2015 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
jshock 513 Posted February 20, 2015 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