// Personal Following Device // Ordinal Malaprop // 2006-10-01 (or something like that) // Free for non-commercial use string gName = ""; key gFollowing = NULL_KEY; integer gFollowType = AGENT; integer gLId = 0; list gNameKey = []; integer gTimeoutMax = 20; integer gTimeout = 0; vector gLastDiff = ZERO_VECTOR; stop_follow() { gFollowing = NULL_KEY; llSensorRemove(); llSetText("", ZERO_VECTOR, 0.0); gTimeout = 0; gLastDiff = ZERO_VECTOR; } default { state_entry() { llOwnerSay("Ready - touch to bring up follow target list"); llSetText("", ZERO_VECTOR, 0.0); } listen(integer channel, string name, key id, string message) { integer n = (integer)message * 2; gName = llList2String(gNameKey, n); gFollowing = llList2Key(gNameKey, n + 1); llListenRemove(gLId); llOwnerSay("Starting to follow " + gName); llSetText("Following\n" + gName, <0.0, 1.0, 0.0>, 1.0); llSensorRepeat(gName, gFollowing, gFollowType, 96.0, PI, 0.25); } no_sensor() { if (gFollowing != NULL_KEY) { if (gTimeout++ == 0) { llOwnerSay("Lost track of " + gName + ", waiting to restore contact..."); } else if (gTimeout == gTimeoutMax) { llOwnerSay("Couldn't find " + gName + ", stopping follow"); stop_follow(); } } else { llOwnerSay("Nothing within range to follow"); } if (gTimeout > 0) { // nudge wearer in direction of last known position llApplyImpulse((gLastDiff / 2 - llGetVel()) * llGetMass(), FALSE); } } sensor(integer n) { if (gFollowing == NULL_KEY) { string output = "Please select follow target:\n"; list buttons = []; integer f = 0; string name = ""; if (n > 11) n = 11; gNameKey = []; do { name = llDetectedName(f); gNameKey += [name, llDetectedKey(f)]; output += (string)f + ": " + name + "\n"; buttons += [(string)f]; } while (++f < n); llListenRemove(gLId); integer channel = -llCeil(llFrand(2000000000)); gLId = llListen(channel, "", llGetOwner(), ""); llDialog(llGetOwner(), output, buttons, channel); return; } if (gTimeout > 0) { llOwnerSay("Contact restored with " + gName + ", resuming follow"); gTimeout = 0; } vector vel = llGetVel(); vector pos = llDetectedPos(0); gLastDiff = pos - llGetPos(); float dist = llVecMag(gLastDiff); if (dist > 5.0) { llApplyImpulse((gLastDiff / 2 - vel) * llGetMass(), FALSE); } } on_rez(integer p) { llResetScript(); } touch_start(integer n) { if (gFollowing != NULL_KEY) { llOwnerSay("Stopping follow"); stop_follow(); } else llSensor("", NULL_KEY, gFollowType, 96.0, PI); } attach(key id) { if (id != NULL_KEY) { llResetScript(); } } }