Toumal Posted January 10, 2022 Share Posted January 10, 2022 Hi, I'm trying to find out, in LUA, whether a given zone has units of a particular coalition inside. Getting a callback for when the zone has no units alive inside would be also acceptable. So far I tried MOOSE's onEnterEmpty() which didn't fire, I tried using a filter expression ala SET_GROUP:New():FilterPrefixes("GROUP PREFIX STRING"):FilterActive(true):FilterStart(), but iterating using ForEachGroupAlive() returns me groups that are not nil, but when calling functions on them say they are nil.... So I figured I'd just ask: How can I find out, or get notified, when a zone has for example no red units in it anymore? Link to comment Share on other sites More sharing options...
LG-Skyman Posted January 11, 2022 Share Posted January 11, 2022 Hi, make a SCHEDULER task to periodically filter objects from database, that are in your zone. I think the dead objects should be nil. Smallest interval is 1 second. I can post a snippet later, if you wish.Wysłane z mojego MI MAX 3 przy użyciu Tapatalka Link to comment Share on other sites More sharing options...
Wizxrd Posted January 11, 2022 Share Posted January 11, 2022 I think this might be what you're looking for, but let me know. A function that will search a trigger zone for any object category and check if any of the found objects are of matching coalition. It will return as an array of objects if there is anything found that matches coalition and returns nil if nothing was found that matches coalition. Here's an usage example of the function ScanZone: -- variable for any found units local UnitsInSenakiZone = ScanZone(Object.Category.UNIT, coalition.side.BLUE, "Senaki Zone") -- simple check to print the found units or no found units if UnitsInSenakiZone ~= nil then for _, object in pairs(UnitsInSenakiZone) do trigger.action.outText(object:getName().." is in Senaki Zone", 15) end else trigger.action.outText("no units were found in Senaki Zone", 15) end Here's the script that contains the ScanZone function so you can include in your code/mission: ScanZone.lua 1 Link to comment Share on other sites More sharing options...
Toumal Posted January 12, 2022 Author Share Posted January 12, 2022 19 hours ago, Wizxrd said: I think this might be what you're looking for, but let me know. A function that will search a trigger zone for any object category and check if any of the found objects are of matching coalition. It will return as an array of objects if there is anything found that matches coalition and returns nil if nothing was found that matches coalition. Hey there, thanks a lot for the reply. I gave that function a try, but unfortunately it didn't seem to work quite yet. Let's say I have a trigger zone called "BRAVO ZONE" which the function does find. I did notice that even though the radius in the mission editor was set to 1000, the searchZone.radius turned out to be an odd value: 304.79998779297 Worse, it was extremely inconsistent, sometimes it detected units properly, sometimes it did not. As it turns out, zone points are MSL, and I need to add terrain altitude. The second problem: I have a single unit in BRAVO ZONE, yet when I iterate through the results I get this: 2022-01-12 17:55:45.544 INFO SCRIPTING: Defenders alive in BRAVO 2022-01-12 17:55:45.544 INFO SCRIPTING: ScanZone: Unit found: RED JULIET GROUP-1-1 2022-01-12 17:55:45.544 INFO SCRIPTING: ScanZone: Unit found: RED JULIET GROUP-1-1#001-01 I get these results even after I kill said unit with tank fire from a player controlled tank (which is not part of that group, so that's not the reason for the two units). When I try to check for health getLife or IsAlive I get a nil pointer error. Turns out, the first object is a group, and the second object is the unit. Unless you do your object conditions in the right sequence, you run into nil errors. In the end, I modified the function as follows, which works as expected: function CaucasusPendulum.ScanZone(category, coalition, zoneName) local foundUnits = {} if trigger.misc.getZone(zoneName) ~= nil then local searchZone = trigger.misc.getZone(zoneName) -- new sphere searchVolume from searchZone local searchVolume = { ["id"] = world.VolumeType.SPHERE, ["params"] = { ["point"] = {x=searchZone.point.x, z=searchZone.point.z, y=land.getHeight({x=searchZone.point.x, y=searchZone.point.z})}, ["radius"] = searchZone.radius, } } -- search the volume for an object category world.searchObjects(category, searchVolume, function(obj) -- if the found object is of the same coalition, add it to the table if obj ~= nil and obj:getLife() > 0 and obj:isActive() and obj:getCoalition() == coalition then foundUnits[#foundUnits+1] = obj end end) end if #foundUnits > 0 then -- return the found units return foundUnits end -- return nil if no found units return nil end Thanks a lot for your help, I hope I could contribute back! Link to comment Share on other sites More sharing options...
Wizxrd Posted January 12, 2022 Share Posted January 12, 2022 (edited) To answer some of your questions, the reason the radius is 304.xxx is because it's feet converted to meters. I'm not sure about that change made to ["point"], all it needs basically is the x and y unchanged (at least that's how I've always used it, but if it works, it works :D) As for the issue of finding units that aren't supposed to be in that zone, the only way I could sort of replicate it is if there are units close to the outside perimeter of the zone, < 100 ft will find them "in zone". I wasn't able to reproduce the issue where you returned both a group and unit object within the same foundUnits table, if you sent the Object.Category.UNIT as the category then it will only return unit objects so that one is puzzling me But all in all glad you've made it work for what you needed! Edited January 12, 2022 by Wizxrd Link to comment Share on other sites More sharing options...
Toumal Posted January 12, 2022 Author Share Posted January 12, 2022 Heya, I had the issue that I needed a much larger radius for certain locations - mostly locations with a certain terrain elevation. Since using land.getHeight it works consistently. I think if you do a test case on a mountain top you'll find that you'll need a crazy large radius value for it to work, and zone.radius won't find a thing. As for both unit and group being returned - yes that is the case, even with category.UNIT specified. What I found is that apparently everyone is doing this kind of alive check in their scripts (CTLD for example) which will only pass for the actual unit, not the group. That's appears to be the reason why they don't run into troubles. Link to comment Share on other sites More sharing options...
Recommended Posts