Troops in contact detector script help.

  1. 8 years ago

    Hi, I'm trying to use the profiled unit detection part of the script snippets to make a sort of "firefight detector" script.
    The basic premise is that it needs to detect when Blufor and Opfor units are within approximately 300m of each other and move or create a marker at that location to indicate to the player that friendly units are engaged.
    So far I can create a trigger that will activate if both friendly and enemy units are present within it, but to use this I'd have to fill the entire map area with duplicates of this trigger and I'd get weird behavior if the units were across a trigger boundary.
    The code I'm using is this: ((count ([getposATL thisTrigger, 50, ["EAST","entity"]] call ALIVE_fnc_getNearProfiles)) > 0);. Does anybody know of a way to modify or utilize this in a way that would allow me to check each friendly profile on the map for enemy profiles within 300m, and then move a marker to the friendly profile in question.
    Thanks.

  2. The best way to do it would be to take the side of the player, collect all profiles that belong to that side, and attach a trigger to each one with the code. However, I am not sure if you could actually take this route since I don't think you would actually be able to attach a trigger to a profile.

    Another option that is less desirable but much easier to achieve would be to create a loop that runs every X minutes. When ran, it checks each profile that belongs to to a side and check for nearby enemies, if there is a nearby enemy it will create a marker. I'll try to write something up real quick along those lines.

  3. Edited 8 years ago by SpyderBlack723

    This setup would execute a file every 5 minutes that checks for nearby enemies around each friendly profile and if one is detected, it creates a marker which deletes itself after 3 minutes.

    init.sqf:

    if (isServer) then {
    	[{
    	["BLU_F"] execVM "filename.sqf";
    	}, 300, []] call CBA_fnc_addPerFrameHandler;
    }

    filename.sqf

    private ["_factions"];
    _factions = _this;
    
    //-- Get profile id's
    _profileIDs = [];
    {
    	_profileIDs = _profileIDs + ([ALIVE_profileHandler, "getProfilesByFaction",_x] call ALIVE_fnc_profileHandler);
    } foreach _factions;
    
    //-- Define delete function
    _fnc_deleteMarkerTimer = {
    	_marker = _this;
    	_startTime = serverTime;
    
    	waitUntil {sleep 15; (Servertime - _startTime >= 180) or (({_x distance (getMarkerPos _marker) < 300} count ([] call BIS_fnc_listPlayers)) > 0)};
    	deleteMarker _marker;
    };
    
    
    //-- Get profile position and execute check
    {
    	//-- Get profile and it's position
    	_profile = [ALIVE_profileHandler, 'getProfile', _x] call ALIVE_fnc_profileHandler;
    	_position = [_profile, 'position', []] call CBA_fnc_HashGet;
    	
    	//-- Check for enemies
    	if (((count ([_position, 300, ["EAST","entity"]] call ALIVE_fnc_getNearProfiles)) > 0)) then {
    		_marker = createMarker [(format ["%1", random 200]), _position];
    		_marker setMarkerType "mil_dot";
    		_marker setMarkerText "Enemy contact";
    		_marker spawn _fnc_deleteMarkerTimer;
    	};
    } forEach _profileIDs;

    So basically, all you need to do is input the faction of any forces that you consider friendlies and insert them into this line

    ["BLU_F"] execVM "filename.sqf";

    that is listed above.. for example, if you are using US RHS as your friendly forces, then you would change it to this

    ["rhs_faction_usarmy_wd","rhs_faction_usarmy_d"," rhs_faction_usmc_wd","rhs_faction_usmc_d"] execVM "filename.sqf";

    --
    Every 5 min it will do a check for every unit that belongs to any of the above factions to see if there is an enemy within 300m. If an enemy is detected, it will create a marker that self deletes after 3 minutes.

  4. Fantastic, thanks for that. I'll try it out tonight when I get home from work.

  5. I've tried it, it's excellent. I'm using one second in the init.sqf and 0.5 seconds in the main code which gives a flashing effect that is brilliant. What I'd like to do is disable this for the player, but changing it to this doesn't seem to work if (!isPlayer _profile) then { _profile = [ALIVE_profileHandler, 'getProfile', _x] call ALIVE_fnc_profileHandler; _position = [_profile, 'position', []] call CBA_fnc_HashGet; }; in fact it breaks the scrip completely and no markers are displayed.
    Any ideas how to get that to work? The problem it causes is that it gives the player an indication any time an enemy is within 300m, which is not something I'd want.

  6. Edited 8 years ago by SpyderBlack723

    Wait it actually worked on the first try, this can't be right....

    Yeah you can use a hash stored in the profile to check if it's a player, quick edit coming up.

    Edit:

    if !([_profile,"is_player",false] call CBA_fnc_HashGet) then {

    would replace your if (!isPlayer _profile) then {
    line. It's the same concept, will execute the code block underneath it if the profile is not a player, and will execute an else code block if it is a player. I've edited the originally posted code to incorporate this.

    Here's a question, do you ever join any (profiled) AI squads? If so there would be better approach to it so that the squad you are attached to has the combat indicator marker removed.

  7. I've copied that in from your edited original and it's still displaying on the player.
    In the missions that I'm making for this I don't ever join AI squads, so if that method would be dependent on doing so then it wouldn't work for me, but it might be of use to other people.

  8. Edited 8 years ago by SpyderBlack723

    Well if that for some reason didn't work then might as well do it as it's the only other option.

    At the very worst we just check if there are any players within range of the marker and if so delete it.

  9. Ok I re-re-edited the originally posted code, try now.

  10. That's still showing on the player. Unfortunately this has gone past my understanding of scripting so it's difficult for me to work out what's going on with it. I'm an engineer, I'm really not much of a coder.
    Deleting the marker if the player is within range might actually be better though, as if the player is within range they should have to work out the exact location themselves rather than getting a marker to exactly where they need to go. How would that be done?

  11. Ok, I've re-re-re-edited the originally posted code for what hopefully is the solution. Once the marker is created, it spawns a function which checks once every 15 seconds whether the marker has been "alive" for over 180 seconds or whether a player is within 300m. When either of those conditions become true, the marker is deleted.

  12. My init.sqf currently reads:

    [{
    ["rhs_faction_usarmy_d","rhs_faction_usmc_d"] execVM "Scripts\contact.sqf";
    }, 1, []] call CBA_fnc_addPerFrameHandler;

    I've changed the waitUntil line to read:

    waitUntil {sleep 0.5; (Servertime - _startTime >= 0.45) or (({_x distance (getMarkerPos _marker) < 300} count ([] call BIS_fnc_listPlayers)) > 0)};

    When the player is within 300m it displays the normal (flashing once every second) behavior on all units including the player. When the player is outside of that distance the markers are spawned but not deleted, and they duplicate at the rate of one every second.
    I'm a bit lost with this, so reporting what I'm seeing is about as much useful input as I can manage.

  13. Ok, I think I've got it. I moved the player detection part to make the entire code this:

    private ["_factions"];
    _factions = _this;
    
    //-- Get profile id's
    _profileIDs = [];
    {
    	_profileIDs = _profileIDs + ([ALIVE_profileHandler, "getProfilesByFaction",_x] call ALIVE_fnc_profileHandler);
    } foreach _factions;
    
    //-- Define delete function
    _fnc_deleteMarkerTimer = {
    	_marker = _this;
    	sleep 0.5;
    	deleteMarker _marker;
    };
    
    
    //-- Get profile position and execute check
    {
    	//-- Get profile and it's position
    	_profile = [ALIVE_profileHandler, 'getProfile', _x] call ALIVE_fnc_profileHandler;
    	_position = [_profile, 'position', []] call CBA_fnc_HashGet;
    
    	//-- Check for enemies
    	if (((count ([_position, 300, ["EAST","entity"]] call ALIVE_fnc_getNearProfiles)) > 0)) then {
    		_marker = createMarker [(format ["%1", random 200]), _position];
    		_marker setMarkerType "mil_warning";
    		_marker setMarkerText "Troops In Contact";
    		_marker setMarkerColor "ColorOPFOR";
    		_marker spawn _fnc_deleteMarkerTimer;
    		if (({_x distance (getMarkerPos _marker) < 300} count ([] call BIS_fnc_listPlayers)) > 0) then {
    		deleteMarker _marker;
    		};
    	};
    } forEach _profileIDs;

    It works like that. The markers display correctly (flashing) when the player is outside 300m. When the player moves to within 300m all markers are removed. That's exactly what I wanted.

    Thanks a lot for this, it's going to be really helpful in my mission for helping players get into the action.

  14. Edited 8 years ago by SpyderBlack723

    You could change that a bit to avoid needlessly creating a marker when you're only going to delete the marker anyway.

    //-- Get profile position and execute check
    {
    	//-- Get profile and it's position
    	_profile = [ALIVE_profileHandler, 'getProfile', _x] call ALIVE_fnc_profileHandler;
    	_position = [_profile, 'position', []] call CBA_fnc_HashGet;
    
    	//-- Check for enemies
    	if ((((count ([_position, 300, ["EAST","entity"]] call ALIVE_fnc_getNearProfiles)) > 0)) and (({_x distance _position < 300} count ([] call BIS_fnc_listPlayers)) == 0)) then {
    		_marker = createMarker [(format ["%1", random 200]), _position];
    		_marker setMarkerType "mil_warning";
    		_marker setMarkerText "Troops In Contact";
    		_marker setMarkerColor "ColorOPFOR";
    		_marker spawn _fnc_deleteMarkerTimer;
    	};
    } forEach _profileIDs;

    That should work unless I fucked up a parentheses somewhere.

  15. Yeah, I can confirm that that works as well, and as you say it's a more efficient way of doing it.
    It's also nice that the two radii can be different if desired, so you can remove the markers if the player is within 1k but detect troops in contact with enemy within 300m.
    Running it every 1s makes for a fantastic flashing effect that really draws attention to the marker, and I like the fact that it can be active at multiple locations simultaneously. It could also be used as a FLOT indicator easily by changing the marker type and duration.

    As I said, thanks a lot for this, it's going to add a lot to my scenario (which I really should post here somewhere if I ever stop fiddling with it!).

  16. Just a quick one, if I change the marker name to a global instead of local (so "_marker" to "marker", would that restrict it to one marker at a time? That would actually be quite handy.

  17. Edited 8 years ago by SpyderBlack723

    It would not restrict it, the name is the only thing about it that needs to be unique. Currently the name is a random number 0-200 and that includes decimals so their is a low chance that two marker names will be the same (You can raise it however).

 

or Sign Up to reply!