Petey Carver Posted April 11 Share Posted April 11 I need to update my radar listed second below that uses sensor to use llGetAgentList listed first below so that it will work for the entire region. It works with Primsave so it needs to keep the same output. What's the best way to do that? llGetAgentList //https://wiki.secondlife.com/wiki/LlGetAgentList // Orders new list based on distance // and returns names and distances on touch default { touch_start(integer num_detected) { list keys = llGetAgentList(AGENT_LIST_REGION, []); integer numberOfKeys = llGetListLength(keys); vector currentPos = llGetPos(); list newkeys; key thisAvKey; integer i; for (i = 0; i < numberOfKeys; ++i) { thisAvKey = llList2Key(keys,i); newkeys += [llRound(llVecDist(currentPos, llList2Vector(llGetObjectDetails(thisAvKey, [OBJECT_POS]), 0))), thisAvKey]; } newkeys = llListSort(newkeys, 2, FALSE); // sort strided list by descending distance for (i = 0; i < (numberOfKeys * 2); i += 2) { //llOwnerSay(llGetDisplayName(llList2Key(newkeys, i+1)) llSay(0,llGetDisplayName(llList2Key(newkeys, i+1)) +" ["+ (string) llList2Integer(newkeys, i) + "m]"); } } } Radar ///////////////////// User variables: /////////////////////////////// // If the scan-distance is a sphere, this cuts off the bottom & top. float ceiling = 90 ; // how high above the rezz-prim do we stop detecting float floor = -90 ; // how low below the rezz-prim do we stop detecting, use negative integer height_adjusted = 1 ; // Set to 1 to activate, 0 to de-activate to reduce lag integer set_name = 0 ; // This sets the name of for what avi came first in the scan, as // hover text over the rezzer. integer rezzer_coms__C = -940369920 ; // The channel that is used for all // rezzers in the sim, to communicate & give commands. // Below here nothing needs to be changed for proper operation // ////////////////////////////////////////////////////////////////// integer periodic_clean = 0 ; //a boolean that will be set when the next sensor is to do a simple clean vector prim_z ; // the height of the rezzer at rezz-time (not on script reset) integer to_rez_prims = 0 ; // How many prims will this rezzer rezz ? integer message_given = FALSE ; // prevents error message to be repeated float scan_distance = 3 ; // distance to the avatar integer rezzed = 0 ; // keep track of whether objects where rezzed already integer position ; // counts down a number of Position commands after rezz, // because it turns out sometimes objects are rezzed, but do not position. // In all cases thusfar, one Position command did it. // Never did a Clean command not derezz everything integer avDistance; vector rPos; integer i; // A function that returns the amount of free prims on the land. integer check_free ( integer verbose ) { integer max ; //maximum prims allowed integer here ; // prims that are rezzed, total count max = llGetParcelMaxPrims ( llGetPos ( ) , TRUE ) ; here = llGetParcelPrimCount ( llGetPos ( ) , PARCEL_COUNT_TOTAL , TRUE ) ; if ( verbose ) { llWhisper ( 0 , "free prim space: " // + " rezzed: " + ( string ) here + " free: " + ( string ) ( max - here ) ) ; } return max - here ; // how many still allowed } // rezzes the stuff rezz ( ) { if ( 3 != rezzed ) // unrezzed { if ( to_rez_prims < check_free ( 0 ) ) { // there are enough prims free ///////////// Set name on rezzer: if ( set_name ) { string avin ; // the one who entered (first) avin = llDetectedName ( 0 ) ; // find avi to give message llSetText ( avin , < 1 , 0 , 1 > , .4 ) ; // For the Fairy Inn, determines who owns the house } //////////// ^ rezzed = 3 ; // keep track of rezzed status //llSay ( 0 , "Optional rezz message" ) ; // <--> here we rezz stuff // check if the primspace is there: // HERE WE ARE DOING THE REZZ COMMAND: llMessageLinked ( LINK_THIS , 0 , // unused "Build" , // copy over the received message "" ) ; // copy over, but it is unused position = 16 ; // We say on the coms what we do. llRegionSay ( rezzer_coms__C , "rezzing" + ":" + ( string ) to_rez_prims ) ; } else // not enough free prims, give message once { key avi ; // the one who entered (first) avi = llDetectedKey ( 0 ) ; // find avi to give message if ( FALSE == message_given ) { llRegionSayTo ( avi , 0 , "Not enough free prim space" ) ; message_given = TRUE ; // remember to prevent spam } } } // We have to give the position order repeatedly, lag issues etc. if ( position ) // run down the positioning calls { if ( 0 == ( position % 5 ) ) // on ever count to 5, 3 times { llMessageLinked ( LINK_THIS , 0 , // unused "Position" , // copy over the received message "" ) ; // copy over, but it is unused } position -- ; } } de_rezz ( ) { message_given = FALSE ; // reset if ( rezzed ) { //llSay ( derezz_channel , "derezz" ) ; // <--> here we derezz stuff llMessageLinked ( LINK_THIS , 0 , // unused "Clean" , // copy over the received message "" ) ; // copy over, but it is unused if ( 3 == rezzed ) { //llSay ( 0 , "Optional de-rezz-message" ) ; llRegionSay ( rezzer_coms__C , "deleting" + ":" + ( string ) to_rez_prims ) ; } rezzed -- ; // keep track of rezzed status } else if ( periodic_clean ) { // <--> here we derezz stuff llMessageLinked ( LINK_THIS , 0 , // unused "Clean" , // copy over the received message "" ) ; // copy over, but it is unused periodic_clean = 0 ; // Done it, prevent re-execution on next sensor } ///////////// Set name on rezzer: llSetText ( "" , < 1 , 0 , 1 > , 1 ) ; // clear ///////////// ^ } /* utility function from public library */ string left(string src, string divider) { integer index = llSubStringIndex( src, divider ); if(~index) return llDeleteSubString( src, index, -1); return src; } string right(string src, string divider) { integer index = llSubStringIndex( src, divider ); if(~index) return llDeleteSubString( src, 0, index + llStringLength(divider) - 1); return src; } default { on_rez ( integer in ) { llResetScript ( ) ; } state_entry ( ) { scan_distance = ( float ) ( left ( llGetObjectDesc ( ) , "#" ) ) ; // object description field sets scan-distance. to_rez_prims = ( integer ) ( right ( llGetObjectDesc ( ) , "#" ) ) ; // object description field sets scan-distance. llSay ( 0 , "Scan distance (objdesc): " + ( string ) scan_distance + " meter. This rezzer rezzes: " + ( string ) to_rez_prims + " LI/prims" ) ; llSensorRepeat( "", NULL_KEY , AGENT , scan_distance , PI , 2.0 ); // the number is the range to search 96 = max // It turns out that sometimes by lag there are still objects that remain // rezzed despite the sensor system, probably because the object-rezzing is so // slow/lagged that they are rezzed after that the cleaning already has passed. // Therefore here is a periodic check & clean system, on a slower time tick to // reduce adding lag. Since nothing should be rezzed, or after one succesful clean // nothing remains rezzed, the clean command given will not be qued to other // scripts, because they are no longer there. Hence it should not be causing a // lot of lag anyway. // uncomment to use: // llOwnerSay ( "Rezzer script initiation delay (30-60 seconds)..." ) ; // llSleep ( 30 + ( integer ) llFrand ( 30 ) ) ; // This causes the timer to start at random, // so that not all these rezzers will do their periodic clean at the same second. // They could otherwise be close to each other, when they are rezzed out by the Crown. // Incidentally this also makes the Crown rezzing a little more comfortable, because // some large distance rezzers will start rezzing themselves automatically, if people // are even merely at ground level where the Crown is. llSetTimerEvent ( 60 ) ; // This seems to be fairly reasonable. llOwnerSay ( "Operational ..." ) ; } timer( ) { // We are going to set a boolean, that will be used by the next sensor-sweep to do a // one time simple additional cleaning command, regardless of what is thought to be rezzed // by this script. It is not worth the additional trouble to create a check toward rezzed // objects periodic_clean = 1 ; // Next no-sensor will do a simple additional clean. } // The key code of the sencor and no-sencor events is written as a function, // because the no-sencor event is executed both by itself, and the sencor // event which is turned into a no-sencor event if the avi is detected in // the exclusion zones sensor ( integer number ) { if ( height_adjusted ) // going to reject the scan find if out of high/low bounds // This is meant to reduce lag, as it is often executed { // Compare z-axis (vertical), if the avi is outside the range, // the whole sensor should not have activated and hence all code // is skipped. vector location_avi = llDetectedPos ( 0 ) ; // Where is the avi // Detected in range, now detract the top/bottom ends. prim_z = llGetPos ( ) ; // where is the rezzer if ( ( ( floor + prim_z.z ) < location_avi.z ) && // avi above floor ( ( ceiling + prim_z.z ) > location_avi.z ) ) // avi below ceiling {// inside of sensor-range rezz ( ) ; // This is de-facto the sencor event } else { de_rezz ( ) ; // turn the sencor in the no_sencor event } } else // We don't care about the height limits, and so it is always a good sensor find. { rezz ( ) ; } } // sensor does not detect owner if it's attached no_sensor() { de_rezz ( ) ; // remove it } } Link to comment Share on other sites More sharing options...
Qie Niangao Posted April 12 Share Posted April 12 If there's not already a timer() event handler, one might simply replace the call to llSensorRepeat with a llSetTimerEvent with the same interval, and then move the logic in the existing sensor() and no_sensor() events into a new timer() event, stepping through the list returned by llGetAgentList() the way the sensor events stepped through llDetected* agents. Here the existing timer() event is pretty simple and apparently driven by a global counter on the same interval, so could probably stay there with a little tweaking, but… … problem is, I can't figure out how this existing code steps through the agents detected by the sensor. The llDetected* function calls only use the zero-th detection (so the one sensed agent nearest the sensor), so… I guess I'm stumped. Are we sure this sensor code is actually doing the thing that instead would be done with llGetAgentList ? If we really only care about the nearest agent, I guess we could step through that list hunting for it by llVecDist between each agent's OBJECT_POS and the scripted object's position, but is that really what this script is trying to do? (I have no idea what Primsave is, but it sorta doesn't matter until I understand how the sensor results work.) Link to comment Share on other sites More sharing options...
Petey Carver Posted April 12 Author Share Posted April 12 The radar keeps the build rezzed while an avatar is in range. It doesn't report any specific names. So, that is also what I was trying to figure out. Does it need some logic like no agents found, or check each agent found for in range or not and does llGetAgentList work that way. Primsave tells your rezzer to keep a build rezzed while avatars are in range, and derez when no avatars are in range. You put the range and number of prims in the object description like this 45#112 and the ceiling and floor in the script. Link to comment Share on other sites More sharing options...
Qie Niangao Posted April 12 Share Posted April 12 (edited) Ah okay so it really is only conditional on the presence of one avatar in range. Unfortunately, as the wiki says of llGetAgentList, "There is no guaranteed understandable order or randomness to the list returned" so the timer() logic will need to loop through that list, terminating when it finds one in range, and if it exhausts the list without finding any, de_rezz as in the current no_sensor() event. And if it does find one in range, that corresponds to whatever is done in the current sensor() event. The periodic_clean variable is currently set by the timer() event which triggers the next de_rezz to send an extra "Clean" message. What might work instead is a global timestamp of when the last such cleaning happened, and let de_rezz check if llGetTime() has gone longer than that 60-second periodic cleaning interval, and if so, send the extra message and update the global timestamp. Edited April 12 by Qie Niangao Link to comment Share on other sites More sharing options...
Petey Carver Posted April 12 Author Share Posted April 12 (edited) Thanks, that clears up that issue! The wiki has an example of sorting the list // Orders new list based on distance // and returns names and distances on touch default { touch_start(integer num_detected) { list keys = llGetAgentList(AGENT_LIST_REGION, []); integer numberOfKeys = llGetListLength(keys); vector currentPos = llGetPos(); list newkeys; key thisAvKey; integer i; for (i = 0; i < numberOfKeys; ++i) { thisAvKey = llList2Key(keys,i); newkeys += [llRound(llVecDist(currentPos, llList2Vector(llGetObjectDetails(thisAvKey, [OBJECT_POS]), 0))), thisAvKey]; } newkeys = llListSort(newkeys, 2, FALSE); // sort strided list by descending distance for (i = 0; i < (numberOfKeys * 2); i += 2) { llOwnerSay(llGetDisplayName(llList2Key(newkeys, i+1)) +" ["+ (string) llList2Integer(newkeys, i) + "m]"); } } } Edited April 12 by Petey Carver Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now