// Push alert script - beta // This is designed to alert you to being pushed more than 50m in one second. // It then gives you the option to teleport back, tells you who was around // the area that you left, and tells you if you were // hit by scripted objects and who they were owned by. // Ordinal Malaprop // 2006-07-01 string gReport = ""; vector gPos = ZERO_VECTOR; // this is a global position string gRegion = ""; list gHitBy = []; integer gObject = 0; integer gLId = 0; list gAvatars = []; // Maximum distance to allow movement within 1s - increase or reduce as desired. float gMaxDistance = 40.0; update() { gRegion = llGetRegionName(); gPos = llGetRegionCorner() + llGetPos(); gHitBy = []; } integer moved_too_far(vector pos) { // llOwnerSay((string)llVecDist(gPos, pos)); return (llVecDist(gPos, pos) > gMaxDistance); } launch_menu() { llListenRemove(gLId); integer channel = -llCeil(llFrand(2000000000)); llDialog(llGetOwner(), gReport, ["Teleport", "Reset", "Cancel"], channel); gLId = llListen(channel, "", llGetOwner(), ""); } default { state_entry() { llOwnerSay("Scanning"); llSetText("Scanning", <1.0, 1.0, 0.0>, 1.0); update(); // Checks position every 1s llSetTimerEvent(1.0); // Scans for avatars in your area every 5s llSensorRepeat("", NULL_KEY, AGENT, 96.0, PI, 5.0); } sensor(integer n) { // If avatars sensed, add their names and distances to the list gAvatars = []; vector pos = llGetPos(); integer f = 0; do { gAvatars += (llDetectedName(f) + " @ " + (string)llRound(llVecDist(llDetectedPos(f), pos)) + "m"); } while (++f < n); } no_sensor() { // If avatars not sensed, clear the list gAvatars = []; } timer() { // Check whether you've moved too far in the last second vector pos = llGetPos(); if (moved_too_far(llGetRegionCorner() + pos)) state triggered; // If not, updated current position update(); } collision_start(integer n) { // If collide with scripted objects, add their owners' keys to the list // Don't get the names yet, they may not be in the same sim. integer f = 0; do { if (llDetectedType(f) & SCRIPTED) { gHitBy += llGetOwnerKey(llDetectedKey(f)); } } while (++f < n); } changed(integer change) { // If you've teleported, don't trigger the device if (change & CHANGED_TELEPORT) { update(); } } // Don't want to trigger on logging in or rezzing, either on_rez(integer p) { update(); } attach(key id) { update(); } } state triggered { state_entry() { // Stop the timer, we don't need it when triggered llSetTimerEvent(0.0); llSetText("Triggered", <1.0, 0.0, 0.0>, 1.0); // Find the distance moved vector pos = llGetRegionCorner() + llGetPos(); gReport = "Push warning triggered - moved " + (string)llRound(llVecDist(pos, gPos)) + "m."; // Did we change region? if (gRegion != llGetRegionName()) { gReport += " You were in " + gRegion + " and are now in " + llGetRegionName() + "."; } // Were we hit by anything? if (gHitBy == []) { gReport += "\nYou did not collide with any scripted objects."; } else { gReport += "\nYou collided with " + (string)llGetListLength(gHitBy) + " scripted object(s)."; llOwnerSay("Requesting scripted collision object owner data, please wait...."); // Start using dataserver calls to get the names of the owners gObject = 0; while (llList2Key(gHitBy, gObject) == NULL_KEY) { llOwnerSay("Object owner key not detected"); gObject++; } llRequestAgentData(llList2Key(gHitBy, gObject), DATA_NAME); } // Was there anyone around? if (gAvatars == []) { gReport += "\nNo avatars within 96m"; } else { gReport += "\nFound: " + llList2CSV(gAvatars); } llOwnerSay(gReport); // Now start the menu that allows TPing and resetting launch_menu(); } dataserver(key query, string data) { // Should return the name of the object owner that hit us llOwnerSay("Hit by object owned by " + data); if (++gObject < llGetListLength(gHitBy)) { while (llList2Key(gHitBy, gObject) == NULL_KEY) { llOwnerSay("Object owner key not detected"); gObject++; } llRequestAgentData(llList2Key(gHitBy, gObject), DATA_NAME); } } listen(integer c, string name, key id, string msg) { llListenRemove(gLId); // Process menu commands if (msg == "Teleport") { llMapDestination(llGetRegionName(), gPos - llGetRegionCorner(), ZERO_VECTOR); state default; } else if (msg == "Reset") { state default; } else if (msg == "Cancel") { llOwnerSay("Staying in triggered mode - you can activate this action menu again by touching the HUD"); } } touch_start(integer n) { // Launch the command menu if touched in triggered state as well launch_menu(); } // Reset on attachment or rez attach(key id) { state default; } on_rez(integer p) { state default; } state_exit() { llListenRemove(gLId); } }