doc. caliban 34 Posted March 5, 2017 Hello. I am needing to find out which marker areas a unit is within, then determine which of them is the smallest. I need the variable name of that marker returned by the script. I'm guessing it would be something along the lines of this: 1 Use unit inArea against each marker returned by allMapMarkers. 2 Use getMarkerSize against the results of the above line. 3 Determine which marker from the results of step 2 is smallest, and return its variable name. Any help with the actual scripting would be greatly appreciated! -Doc Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 // in init.sqf waitUntil {time > 0}; player linkItem "ItemGPS"; sleep 0.75; hintC "Open your GPS"; // marker area function MarkerArea = { switch (markerShape _this) do { case "RECTANGLE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh}; case "ELLIPSE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh * 0.25 * pi}; default {0} } }; // create list of all markers ordered by area allMapMarkersOrderedByArea = [allMapMarkers,[],{_x call MarkerArea},"ASCEND"] call BIS_fnc_sortBy; // poll smallest marker with player and log in system chat while {true} do { private _smallestMarker = {if (player inArea _x) exitWith {_x}; ""} forEach allMapMarkersOrderedByArea; systemChat ("Player inside marker: " + _smallestMarker); sleep 1; }; Demo mission: link Share this post Link to post Share on other sites
killzone_kid 1331 Posted March 5, 2017 The code above will return the first marker unit is in, what is all business with getting the size and sorting??? Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 13 minutes ago, killzone_kid said: The code above will return the first marker unit is in, what is all business with getting the size and sorting??? Yes, you're right. Code above will return the first marker unit is in, from markers array ordered by marker area, and this is exactly what he needs. // return marker name or empty string if unit outside of any marker SmallestMarkerUnitIsIn = { {if (_this inArea _x) exitWith {_x}; ""} forEach allMapMarkersOrderedByArea}; // Usage: private _marker = player call SmallestMarkerUnitIsIn; Share this post Link to post Share on other sites
killzone_kid 1331 Posted March 5, 2017 What he needs (Step 3) is the smallest marker returned with unit in, and you return any marker with unit in. Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 4 minutes ago, killzone_kid said: What he needs (Step 3) is the smallest marker returned with unit in, and you return any marker with unit in. Not "any", first marker unit in from array of markers ordered from smallest to biggest by area :)) Share this post Link to post Share on other sites
killzone_kid 1331 Posted March 5, 2017 Yes "any". I can walk into the biggest marker, and it will be returned, then I can walk into the smallest marker, and it will be returned. Then, for the final test, I can close my eyes and walk in any random marker, and it will be returned. In my books this is called returning "any" marker. Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 1 minute ago, killzone_kid said: Yes "any". I can walk into the biggest marker, and it will be returned, then I can walk into the smallest marker, and it will be returned. Then, for the final test, I can close my eyes and walk in any random marker, and it will be returned. In my books this is called returning "any" marker. When you walk into area overlapped by three different markers my code returns smallest marker you're in Share this post Link to post Share on other sites
killzone_kid 1331 Posted March 5, 2017 Ok, fair point, but this only works for overlapped markers which there is no mention of in the original request Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 4 minutes ago, killzone_kid said: Ok, fair point, but this only works for overlapped markers which there is no mention of in the original request Anyway, we need for topic starter to clarify :) Share this post Link to post Share on other sites
doc. caliban 34 Posted March 5, 2017 Hello! If I understand, Serena's code is in fact what I need, KK. It's ordering the markers from smallest to largest, and then returns the first one the unit is in in that order. So if the unit is in 4 different areas, it will return the smallest of the 4. If the unit is in any single area, it will return that marker name since that single area is by default the smallest area the unit is in. Thank you, Serena! Here's how I'd like to use this: In the init field of some units, I have a statement that includes an array. One of the string entries in the array is the variable name of a marker. I'd like to utilize this code to output that string value at startup. I currently have a less desirable solution of just getting the nearest marker, like this: [([allMapMarkers, this] call BIS_fnc_nearestPosition), etc...] That works, but can easily be inaccurate since it does not take marker area into account. (Thus this post) I'd like to replace ([allMapMarkers, this] call BIS_fnc_nearestPosition) with Serena's code. Should I precompile it as a function and call it like this? [(call fnc_serenaCode), etc...] It will be running a few dozen times at startup, and then won't be used again during the mission. Thank you again! -Doc EDIT: I just saw the latest 2 replies .... typing a clarification. Stand by... (watch this space) :-) To clarify: Overlapping areas (cases where a smaller area is not completely contained within a larger area) are not an issue for my needs. I just need to work with areas that are completely contained within other areas, or if the unit is only in one area, the name of that area. Does that help? Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 . 16 minutes ago, doc. caliban said: Should I precompile it as a function and call it like this? [(call fnc_serenaCode), etc...] It will be running a few dozen times at startup, and then won't be used again during the mission. Simple variant: // in init.sqf waitUntil {time > 0}; MarkerArea = { switch (markerShape _this) do { case "RECTANGLE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh}; case "ELLIPSE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh * 0.25 * pi}; default {0} } }; allMapMarkersOrderedByArea = [allMapMarkers,[],{_x call MarkerArea},"ASCEND"] call BIS_fnc_sortBy; // Somewhere in scripts (replace player with actual unit) private _marker = {if (player inArea _x) exitWith {_x}; ""} forEach allMapMarkersOrderedByArea; Wrapped variant: // add this to init.sqf SmallestMarkerUnitIsIn = { {if (_this inArea _x) exitWith {_x}; ""} forEach allMapMarkersOrderedByArea}; // Somewhere in scripts (replace player with actual unit) private _marker = player call SmallestMarkerUnitIsIn; * if unit is not in any marker area, an empty string is returned Share this post Link to post Share on other sites
doc. caliban 34 Posted March 5, 2017 My limited understanding of this stuff is really starting to show now. :-) It looks like I could use it in my array like this: [(player call SmallestMarkerUnitIsIn), etc...] That would result in the array containing ["markerName", etc...], correct? If so, to do that I'd need to have this in init.sqf? waitUntil {time > 0}; MarkerArea = { switch (markerShape _this) do { case "RECTANGLE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh}; case "ELLIPSE": {getMarkerSize _this params ["_msw", "_msh"]; _msw * _msh * 0.25 * pi}; default {0} } }; allMapMarkersOrderedByArea = [allMapMarkers,[],{_x call MarkerArea},"ASCEND"] call BIS_fnc_sortBy; SmallestMarkerUnitIsIn = { {if (_this inArea _x) exitWith {_x}; ""} forEach allMapMarkersOrderedByArea}; Off to bed. I'll check this in the morning. Thank you again. This will help massively reduce the time it takes me to make missions. I'll explain once I've got it working. -Doc Share this post Link to post Share on other sites
serena 151 Posted March 5, 2017 6 minutes ago, doc. caliban said: That would result in the array containing ["markerName", etc...], correct? If so, to do that I'd need to have this in init.sqf? Yes and yes. Result also can be ["", etc... ] when unit outside of any marker area. Share this post Link to post Share on other sites
killzone_kid 1331 Posted March 5, 2017 1 hour ago, doc. caliban said: I just need to work with areas that are completely contained within other areas, or if the unit is only in one area, the name of that area Then Serena's code is valid solution for your problem ;) Share this post Link to post Share on other sites
doc. caliban 34 Posted March 5, 2017 Thank you both very much. It's a very specific thing I wanted to be able to do, and while there are certainly fringe cases that it might not handle, those are not of concern for my purposes. Here's what I'm doing: I use the script-only version of the AI mod that's bundled into MCC, Gaia. The mission making process is to place area markers that will be used at Gaia "zones", place groups in the zones, then edit the init for each group leader to define, among other things, the zone they are assigned to. That meant a lot of init editing, which meant a few mistakes in almost every mission. I wanted to make the process more automated and error-proof. I have custom groups saved with the other init settings that I want, so all I have to do is paste them into whatever zones I want, but I still had to edit each group leader's init to specify the zone. With this code the zone will now be automatically set, so my Gaia-related mission making phase is super fast and simple, and pretty much error-proof. I always have zones nested inside of other zones, but rarely have any that partially overlap by much. If they do, it's very little, and I simply don't place groups in the overlapping areas. Every group is in at least one zone, but if I make a mistake and have one that is not, the code returning "" is just fine. It won't hurt a thing. Again, thank you so much... this has been a huge help, and will have a great impact on my missions in that I can spend more time working on the other aspects of them once the basic Gaia zones and troops are laid down. Best, -Doc EDIT: I've run into one snag: Using (this call smallestMarkerUnitIsIn) does not seem to work. Using player instead of this works on myself, but these need to run against AI units, not playable units. I'm sorry if my not specifying that sooner caused a problem! Share this post Link to post Share on other sites