Jump to content
Sign in to follow this  
1para{god-father}

How to change Colour of Marker once condition is meet

Recommended Posts

OK I have managed to make some markers at a random town which are over buildings.

Now I need a way of changing theses, marker to a different colour / or removing them once a condition is meet i.e no opfor or variable = true.

So one of the markers changes colour not all etc..

Creating markers follows:-

private ["_mkr","_var","_pos","_houses"];
/// get all houses in location//////
_houses = [markerpos "taskarea1",600, 3, true] call findHouses;
{
_pos = _x call getGridPos;
_mkr = str _pos;
if (getMarkerPos _mkr select 0 == 0) then {
	_mkr = createMarkerLocal[_mkr, _pos]; 
	_mkr setMarkerShapeLocal "RECTANGLE"; 
	_mkr setMarkerTypeLocal "SOLID";		
	_mkr setMarkerSizeLocal [50,50]; 
	_mkr setMarkerAlphaLocal 0.6; 
	_mkr setMarkerColorLocal "ColorGreen";
};
} forEach _houses;

Share this post


Link to post
Share on other sites

You need to store _mkr variable somewhere (global var perhaps) and then change it with setMarkerColorLocal just like you did when it was initialized.

Share this post


Link to post
Share on other sites

But how would I know which one to change and how would it check all the time?

i.e say it has 6 markers all red bluefor enter 1 marker and there is No Opfor in that marker ,how can i change it to blue ?

Share this post


Link to post
Share on other sites

It looks like, in that code, that the marker name is relevant to the map grid position.

I think the easist way would be to create a trigger that covers the marker area when you create the marker.

I recognize that code from insurgency but it's hard to get a good grip on the insurgency code, at least for me :)

Share this post


Link to post
Share on other sites

Yep taken from Insurgency and just tweaked to just do a random town.

I did think about 1 trigger but it will not work on what i am trying to accomplish as I need the separate markers to change colour or be removed.

Just cannot work out how to Ref them?

Share this post


Link to post
Share on other sites

Your inbox is full.

Well it sort of depends on how many markers you've got. I am not sure how insurgency checks it but I'd assume that there is a loop constantly checking the players location, if he's inside a red marker it will check for enemies and if there are no enemies it will change color.

You could do like insurgeny does it and just name the markers after their curent grid position, something like:

_m=createMarker [format ["%1",mapGridPosition _pos],_pos];

And check player position with

_x = (getPosATL player select 0);
_y = (getPosATL player select 1);
_pos = mapGridPosition [(_x-(_x mod 100)-50),(_y-(_y mod 100)-50)];
_marker = str _pos;
_marker setMarkerColor "ColorGreen";

You could just count the nearest enemies from there, but it would count in a circle, not rectangle.

I'm just guessing here, I haven't tested the code.

If I'm not wrong, insurgency checks the houses, not nearest enemies.

Share this post


Link to post
Share on other sites

Best to create a global array such as:

mymissionmarkers = [];

then store local variables which you need to access later into that array via:

mymissionmarkers = mymissionmarkers + [_markername1,_markername2, etc...];

You could then find the nearest marker to whichever unit has triggered the particular condition ( I am not sure what the conditions are that your planning to use so this is just a guess).

private["_temparray","_tempvariable","_closestmarker"];
//-- REMOVE DASHES IF YOU WANT A SORTED LIST OF MARKERS BY DISTANCE --// _temparray = [];
_tempvariable = mymissionmarkers ;
{
_closestmarker = _tempvariable select 0;
{if (((getmarkerpos _x) distance _insertunitname) < (_closestmarker distance _insertunitname)) then {_closestmarker = _x}} forEach _tempvariable;
//-- REMOVE DASHES IF YOU WANT A SORTED LIST OF MARKERS BY DISTANCE --// _temparray = _temparray + [_closestmarker];
_tempvariable = _tempvariable - [_closestmarker]
} forEach _tempvariable;
// _closestmarker is the marker closest marker

Edited by Rejenorst

Share this post


Link to post
Share on other sites

Thanks guys:-

Never used arrays before so how would I store the markersif generating a lot of them , see Red below is that correct ?

[color="#FF0000"]mymissionmarkers = [];[/color]
private ["_mkr","_var","_pos","_houses"];
/// get all houses in location//////
_houses = [markerpos "taskarea1",600, 3, true] call findHouses;
{
_pos = _x call getGridPos;
_mkr = str _pos;
if (getMarkerPos _mkr select 0 == 0) then {
	_mkr = createMarkerLocal[_mkr, _pos]; 
	_mkr setMarkerShapeLocal "RECTANGLE"; 
	_mkr setMarkerTypeLocal "SOLID";		
	_mkr setMarkerSizeLocal [50,50]; 
	_mkr setMarkerAlphaLocal 0.6; 
	_mkr setMarkerColorLocal "ColorGreen";
};
[color="#FF0000"]
// would I add it here if so is this correct ?
mymissionmarkers = mymissionmarkers +_mkr;[/color]


} forEach _houses;

Share this post


Link to post
Share on other sites

Hi mate...

mymissionmarkers = mymissionmarkers + [_mkr];

or.. more efficient...

mymissionmarkers set [count mymissionmarkers,_mkr];

Share this post


Link to post
Share on other sites

Yep sorry forgot about the set method.

So Yes, or alternatively:

mymissionmarkers = [];
private ["_mkr","_var","_pos","_houses"];
/// get all houses in location//////
_houses = [markerpos "taskarea1",600, 3, true] call findHouses;
{
_pos = _x call getGridPos;
_mkr = str _pos;
if (getMarkerPos _mkr select 0 == 0) then {
	_mkr = createMarkerLocal[_mkr, _pos]; 
	_mkr setMarkerShapeLocal "RECTANGLE"; 
	_mkr setMarkerTypeLocal "SOLID";		
	_mkr setMarkerSizeLocal [50,50]; 
	_mkr setMarkerAlphaLocal 0.6; 
	_mkr setMarkerColorLocal "ColorGreen";
};

// would I add it here if so is this correct ?
mymissionmarkers set [count mymissionmarkers, _mkr];


} forEach _houses;

TRIGGER AND SCRIPT POSSIBILITY 1:

Yep now all you would have to do in the trigger is:

{_x _setMarkerColorLocal "ColorGreen"} foreach mymissionmarkers;

TRIGGER AND SCRIPT POSSIBILITY 2:

However if you just want to change marker colors that are within a _radius of a particular _unit or object then:

[_unit,_radius] execVM "scriptname.sqf";

This may have to be:

0 = [_unit,_radius] execVM "scriptname.sqf";

Change the scriptname to whatever you want (just make sure the scriptname.sqf is changed accordingly) then copy paste this in:

private["_closestmarkers","_radius","_unit"];
_unit = _this select 0;
_radius = _this select 1;
_closestmarkers = [];
{if ((_unit distance (getmarkerpos _x)) <= _radius) then {_closestmarkers = _closestmarkers + [_x]};} foreach mymissionmarkers;
if ((count _closestmarkers) > 0) then 
{
{_x setMarkerColorLocal "ColorRed"} foreach _closestmarkers;
};		

This will check how far the unit is away from the markers you placed in the mymissionmarkers variable and if they are less than or equal to the distance of the radius you specified they will change to color red (change as you see fit).

TRIGGER AND SCRIPT POSSIBILITY 3:

Alternatively you could put this in the trigger:

[_unit] execVM "scriptname.sqf";

This may have to be:

0 = [_unit] execVM "scriptname.sqf";

And then use this code to turn the first 3 closest markers to the unit red:

private["_temparray","_tempvariable","_unit"];
_unit = _this select 0;
_tempvariable = mymissionmarkers ;
{
_closestmarker = _tempvariable select 0;
{if (((getmarkerpos _x) distance _unit) < (_closestmarker distance _unit)) then {_closestmarker = _x}} forEach _tempvariable;
_temparray = _temparray + [_closestmarker];
_tempvariable = _tempvariable - [_closestmarker]
} forEach _tempvariable;
if ((count temparray) > 0) then
{
(temparray select 0) setMarkerColorLocal "ColorRed";
if ((count temparray) > 1) then
{
	(temparray select 1) setMarkerColorLocal "ColorRed";
	if ((count temparray) > 2) then
	{
		(temparray select 2) setMarkerColorLocal "ColorRed";
	};
}:
};

Edited by Rejenorst

Share this post


Link to post
Share on other sites
Hi mate...

mymissionmarkers = mymissionmarkers + [_mkr];

or.. more efficient...

mymissionmarkers set [count mymissionmarkers,_mkr];

Sorry guys but really having issues and need some Expert help as this is a bit over my head :)

My mission generates the markers but I need help on the following:-

1) How do I reference the markers so i can use them later to spawn stuff into , and Delete them all once mission has finished

2) How can I change the color of markers when bluefor enter a marker and no opfor are in the marker, and change it back once Opfor enter it again.

Task1.sqf

private ["_mkr","_var","_pos","_houses"];
mymissionmarkers = [];
_gamelogic = center;
_towns = nearestLocations [getPosATL _gamelogic, ["NameVillage","NameCity","NameCityCapital"], 25000]; 
_RandomTownPosition = position (_towns select (floor (random (count _towns)))); 
_marker = createMarker [format ["mrk%1",random 100000],_RandomTownPosition]; 
sleep .2;

_houses = [markerpos _marker,600, 3, true] call findHouses;
{
_pos = _x call getGridPos;
_mkr = str _pos;
if (getMarkerPos _mkr select 0 == 0) then {
	_mkr = createMarkerLocal[_mkr, _pos]; 
	_mkr setMarkerShapeLocal "RECTANGLE"; 
	_mkr setMarkerTypeLocal "SOLID";		
	_mkr setMarkerSizeLocal [50,50]; 
	_mkr setMarkerAlphaLocal 0.5; 
};
mymissionmarkers set [count mymissionmarkers,_mkr];
} forEach _houses;
diag_log format[mymissionmarkers, time];


///Spawn some OPFOR in to some markers  get number of markers then use a % of marker to pop//////
[color="#FF0000"]
_grpOpfor1 = [getmarkerpos xxxx???xxxxxx, EAST, (configFile >> "CfgGroups" >> "EAST" >> "BIS_TK_INS" >> "Infantry" >> "TK_INS_Group")] call BIS_fnc_spawnGroup;
[_grpOpfor1, getMarkerPos xxxxx???xxxxxx, 100] call bis_fnc_taskPatrol;[/color]

//// Now i need to keep track of markers if no opfor are in markers and bluefor enter change color of marker

Edited by psvialli

Share this post


Link to post
Share on other sites

A very inefficient way of doing it, add this to any sqf script then launch the script with this: 0 = [] execVM "scriptname.sqf";

LAUNCH IT AFTER YOU HAVE CREATED THE MARKERS AND SENT THEM TO THE GLOBAL VARIABLE: mymissionmarkers

Copy paste this into a script. I've tested it out and it will loop and continually check whether there are more WEST than BAD over a particular marker and change color accordingly.

private["_temvariable","_cv","_sc","_vardone","_vardone2","_objects","_marker","_eastside","_westside"];
_vardone = 0;
while {_vardone == 0} do {
_temvariable = [];
{if ((count (nearestObjects [(getmarkerpos _x),["MAN"],25])) > 0) then {_temvariable = _temvariable + [_x]};} foreach mymissionmarkers;
sleep 0.1;
_cv = count _temvariable;
if (_cv > 0) then
{
	_sc = 0;
	_vardone2 = 0;
	while {_vardone2 == 0} do {
		if (_sc < _cv) then
		{
			_marker = _temvariable select _sc;
			_objects = nearestObjects [(getmarkerpos _marker),["MAN"],25];
			_westside = [];
			_eastside = [];
			{if (side _x == WEST) then {_westside = _westside + [_x]};} foreach _objects;
			{if (side _x == EAST) then {_eastside = _eastside + [_x]};} foreach _objects;
			if ((count _westside) > (count _eastside)) then
			{
				_marker setMarkerColorLocal "ColorGreen"
				} else {
				if (count _eastside > 0) then 
				{
					_marker setMarkerColorLocal "ColorRed"
				};
			};
			_sc = _sc + 1;
			} else {
			_vardone2 = 1;
		};
	};
};
};

---------- Post added at 10:56 AM ---------- Previous post was at 10:55 AM ----------

I should mention that I haven't placed any terminate conditions so the script will loop forver. You can add a condition that will set _vardone = 1 for the script to exit the loop.

---------- Post added at 10:58 AM ---------- Previous post was at 10:56 AM ----------

Markers react to units within 25 meter distance of marker.

---------- Post added at 10:59 AM ---------- Previous post was at 10:58 AM ----------

Also if you want them to react to tanks, cars, helis etc then add: ,"TANK","AIR","CAR","TRUCK" etc to wherever you see "MAN"

---------- Post added at 11:08 AM ---------- Previous post was at 10:59 AM ----------

Just in case your not sure what to do (sorry just want to help u as fast as possible) copy paste the code into a wordpad and save it into your mission root directory under a name like: markerloop.sqf

At the bottom of your initial Task1.sqf (at the very bottom to make sure this executes after task1.sqf has finished_:

0 = [] execVM "markerloop.sqf";

And that should do it.

Warning though: To many markers and this script will probably slow your performance down quite a bit. Like I said its not efficient in the least but I hope it helps you as a temporary script.

Share this post


Link to post
Share on other sites

WOW many thanks that will help a lot !!

All works Great now !

Next question:-

1) how would I go about deleting the markers once the task is complete?

2) how can i get a list of the array and select say 50% so i can use them to spawn in some groups?

Thanks for all your help guys !

Edited by psvialli

Share this post


Link to post
Share on other sites

1) deleting all the markers or just the markers of the areas cleared? (needs to be very specific.

If you want to delete all of them it would be as simple as putting the line of code:

{deletemarker _x} foreach mymissionmarkers;

However you would need to terminate the script I gave you before hand otherwise you'd get errors popping up if you suddenly delete markers that a script is still using.

If you just want to delete markers as they go green (when captured by friendlies then add the following:

private["_temvariable","_cv","_sc","_vardone","_vardone2","_objects","_marker","_eastside","_westside"];
_vardone = 0;
while {_vardone == 0} do {
_temvariable = [];
{if ((count (nearestObjects [(getmarkerpos _x),["MAN"],25])) > 0) then {_temvariable = _temvariable + [_x]};} foreach mymissionmarkers;
sleep 0.1;
_cv = count _temvariable;
if (_cv > 0) then
{
	_sc = 0;
	_vardone2 = 0;
	while {_vardone2 == 0} do {
		if (_sc < _cv) then
		{
			_marker = _temvariable select _sc;
			_objects = nearestObjects [(getmarkerpos _marker),["MAN"],25];
			_westside = [];
			_eastside = [];
			{if (side _x == WEST) then {_westside = _westside + [_x]};} foreach _objects;
			{if (side _x == EAST) then {_eastside = _eastside + [_x]};} foreach _objects;
			if ((count _westside) > (count _eastside)) then
			{
				_marker setMarkerColorLocal "ColorGreen"
				[b]_temvariable = _temvariable - - [_marker];
				mymissionmarkers = mymissionmarkers - [_marker];
				deletemarker _marker;
				_cv = count _temvariable;[/b]
				} else {
				if (count _eastside > 0) then 
				{
					_marker setMarkerColorLocal "ColorRed"
				};
			};
			_sc = _sc + 1;
			} else {
			_vardone2 = 1;
		};
	};
};
};

However this would defeat the purpose of the markers going green since they would be deleted so fast unless you want to put a seconds wait before the deletion which would be done via

sleep 1; 

If you planning to exit the script and delete all the markers after they are all green then:

private["_temvariable","_cv","_sc","_vardone","_vardone2","_objects","_marker","_eastside","_westside"];
_vardone = 0;
while {_vardone == 0} do {
_temvariable = [];
{if ((count (nearestObjects [(getmarkerpos _x),["MAN"],25])) > 0) then {_temvariable = _temvariable + [_x]};} foreach mymissionmarkers;
sleep 0.1;
_cv = count _temvariable;
if (_cv > 0) then
{
	_sc = 0;
	_vardone2 = 0;
	while {_vardone2 == 0} do {
		if (_sc < _cv) then
		{
			_marker = _temvariable select _sc;
			_objects = nearestObjects [(getmarkerpos _marker),["MAN"],25];
			_westside = [];
			_eastside = [];
			{if (side _x == WEST) then {_westside = _westside + [_x]};} foreach _objects;
			{if (side _x == EAST) then {_eastside = _eastside + [_x]};} foreach _objects;
			if ((count _westside) > (count _eastside)) then
			{
				_marker setMarkerColorLocal "ColorGreen"
				} else {
				if (count _eastside > 0) then 
				{
					_marker setMarkerColorLocal "ColorRed"
				};
			};
			_sc = _sc + 1;
			} else {
			_vardone2 = 1;
		};
	};
};
sleep 0.1;
_temvariable = [];
{if ((getMarkerColor _x) == "ColorGreen") then {_temvariable = _temvariable + [_x]};} foreach mymissionmarkers;
_cv = count _temvariable;
if (_cv == (count mymissionmarkers)) then
{
	_vardone = 1;
};
};
{deletemarker _x} foreach mymissionmarkers;
mymissionmarkers =[];

As for the other question my head is spinning and its late so I'll try and answer it next time,

Share this post


Link to post
Share on other sites

I'll tackle question 2 for you.... see if I can wrap my head around this.

//get a percentage of the count and round it... divide by 3 for 30 percent etc.
_count = round ((count mymissionmarkers)/2);

//copy the mymissionmarkers list... keeping it intact
_oldlist = mymissionmarkers;

//make a new blank list that will contain a percentage of the original markers
_newlist = [];

//randomly select a marker... delete it from the old list so it won't be selected again and add it to the new list
//do this _count number of times
for "_i" from 1 to _count do {
    _mkr = _oldlist select floor (random (count _oldlist));
    _oldlist = _oldlist - [_mkr];
    _newlist set [count _newlist,_mkr];
    sleep 0.01;
};

_newlist should now contain about 50 percent of mymissionmarkers.

Someone may have a more elegant way of doing it but I'm pretty sure that will work.

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  

×