Difference between revisions of "User:Kimm Paulino/Scripts1"

From Second Life Wiki
Jump to navigation Jump to search
m (a few minor readability improvements)
Line 15: Line 15:
integer MAX_REZZED_OBJECTS = 5;
integer MAX_REZZED_OBJECTS = 5;
vector REZ_POSITION = <1.0, 0.0, 0.0>;      // Relative to the rezzing prim, must be less than 10m away
vector REZ_POSITION = <1.0, 0.0, 0.0>;      // Relative to the rezzing prim, must be less than 10m away
vector REZ_ROTATION = <0.0, 0.0, 0.0>;     // In degrees
vector REZ_ROTATION = ZERO_VECTOR;           // In degrees


string gObjectName;
string objectName;


rezObject ()
rezObject ()
{
{
     llRezObject (gObjectName, llGetPos() + REZ_POSITION, ZERO_VECTOR, llEuler2Rot (REZ_ROTATION * DEG_TO_RAD), 0);
    vector currentPosition = llGetPos();
 
     llRezObject (gObjectName, currentPosition + REZ_POSITION, ZERO_VECTOR, llEuler2Rot (REZ_ROTATION * DEG_TO_RAD), 0);
}
}


Line 30: Line 32:
         llResetScript();
         llResetScript();
     }
     }
      
 
     changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
 
     state_entry ()
     state_entry ()
     {
     {
         gObjectName = llGetInventoryName (INVENTORY_OBJECT, 0);
         objectName = llGetInventoryName (INVENTORY_OBJECT, 0);
         if (gObjectName == "")
 
         if (objectName == "")
         {
         {
             llOwnerSay ("Note to owner: No objects found in this prims inventory");
             llOwnerSay ("Note to owner: No objects found in this prims inventory");
         }
         }
     }
     }
   
 
     touch_start (integer num_detected)
     touch_start (integer num_detected)
     {
     {
         if (gObjectName != "")
         if (gObjectName != "")
         {
         {
            // Trigger a single sensor event for the full range/arc looking for any non-avatar
        // Trigger a single sensor event for the full range/arc looking for any non-avatar
            // objects with the same name as our rezzing object.
        // objects with the same name as our rezzing object.
 
             llSensor (gObjectName, NULL_KEY, (ACTIVE|PASSIVE), 96.0, PI);
             llSensor (gObjectName, NULL_KEY, (ACTIVE|PASSIVE), 96.0, PI);
         }
         }
     }
     }
   
 
     sensor (integer num_detected)
     sensor (integer num_detected)
     {
     {
Line 58: Line 70:
         else
         else
         {
         {
        //  Nothing to do
             llOwnerSay ("Max Objects detected ...");
             llOwnerSay ("Max Objects detected ...");
            // Nothing to do
         }
         }
     }
     }
   
 
     no_sensor ()
     no_sensor ()
     {
     {
         // None found, so ok to rez one
         // None found, so ok to rez one
         rezObject();
         rezObject();
    }
   
    changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
     }
     }
}
}
Line 122: Line 127:
// Position of the sittarget
// Position of the sittarget
vector SIT_VECTOR = <0.0, 0.0, 0.5>;    // In metres - ZERO_VECTOR to disable
vector SIT_VECTOR = <0.0, 0.0, 0.5>;    // In metres - ZERO_VECTOR to disable
vector SIT_ROTATION = <0.0, 0.0, 0.0>; // In degrees
vector SIT_ROTATION = ZERO_VECTOR;     // In degrees
 
key avatarOnSitTarget;
integer isSitting = FALSE;


key gAvUuid;
integer gSitting = FALSE;
default
default
{
{
Line 134: Line 139:
     }
     }


    state_entry()
    {
        if (SIT_VECTOR != ZERO_VECTOR)
        {
            llSitTarget (SIT_VECTOR, llEuler2Rot (SIT_ROTATION * DEG_TO_RAD));
        }
        llSetTimerEvent (DEREZ_TIMEOUT);
    }
    timer ()
    {
        if (gAvUuid)
        {
            llUnSit (gAvUuid);
        }
        llSetTimerEvent (0.0);
        llDie();
    }
   
     changed (integer change)
     changed (integer change)
     {
     {
        // When someone sits on an object, the av is considered to be
    // When someone sits on an object, the av is considered to be
        // a linked-in child prim, so the link number changes
    // a linked-in child prim, so the link number changes
 
         if (change & CHANGED_LINK)
         if (change & CHANGED_LINK)
         {
         {
             gAvUuid = llAvatarOnSitTarget();
             avatarOnSitTarget = llAvatarOnSitTarget();
             if (gAvUuid)
             if (avatarOnSitTarget)
             {
             {
                // Avatar has just sat down
            // Avatar has just sat down
                 gSitting = TRUE;
 
                 llSetTimerEvent (DEREZ_AFTER_SIT_TIMEOUT);
                 isSitting = TRUE;
                 llSetTimerEvent(DEREZ_AFTER_SIT_TIMEOUT);
             }
             }
             else if (gSitting)
             else if (isSitting)
             {
             {
                // Assume av just got up - it was sitting and now isn't ...
            // Assume av just got up - it was sitting and now isn't ...
                 gSitting = FALSE;
                 isSitting = FALSE;
                 if (DEREZ_ON_UNSIT)
                 if (DEREZ_ON_UNSIT)
                 {
                 {
                    // Want to derez straight away
                // Want to derez straight away
                     llDie();
                     llDie();
                 }
                 }
                 llSetTimerEvent (DEREZ_AFTER_UNSIT_TIMEOUT);
                 llSetTimerEvent(DEREZ_AFTER_UNSIT_TIMEOUT);
             }
             }
             else
             else
Line 184: Line 172:
             }
             }
         }
         }
    }
    state_entry()
    {
        if (SIT_VECTOR != ZERO_VECTOR)
        {
            llSitTarget(SIT_VECTOR, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD));
        }
        llSetTimerEvent(DEREZ_TIMEOUT);
    }
    timer ()
    {
        if (avatarOnSitTarget)
        {
            llUnSit(avatarOnSitTarget);
        }
        llSetTimerEvent((float)FALSE);//  disable timer
        llDie();
     }
     }
}
}
Line 191: Line 200:


<lsl>
<lsl>
// Basic timer-driven state changing script.
// Basic timer-driven state changing script.
// NB: Does not use the LSL ability to define
// NB: Does not use the LSL ability to define
// states, but uses a counter to manage a simple
// states, but uses a counter to manage a simple
// incrementing state machine.
// incrementing state machine.
//
//
// Every time interval, it will change its record of state
//   Every time interval, it will change its record of state
// and you can add code to do something, then it will move
//   and you can add code to do something, then it will move
// to the next state.
//   to the next state.
//
//
// To add more things, just add more
//   To add more things, just add more
//        else if (gState == 4)
//        else if (currentState == 4)
//        {
//        {
//            // and the next
//            // and the next
//        }
//        }
// statements in the appropriate place.
//   statements in the appropriate place.
//
//
// If you want the timer interval to be different for different
// If you want the timer interval to be different for different
// states, then you could add more llSetTimerEvent() calls
// states, then you could add more llSetTimerEvent() calls
// in each state to set the timer for the next one.
// in each state to set the timer for the next one.
//
//
// Kimm Paulino
// Kimm Paulino
// Sept 2012
// Sept 2012
 
// Timer interval in seconds
// Timer interval in seconds
float TIMER_INTERVAL = 5.0;
float TIMER_INTERVAL = 5.0;


integer gState;
integer currentState;


default
default
Line 225: Line 234:
         llResetScript();
         llResetScript();
     }
     }
   
 
     state_entry ()
     state_entry ()
     {
     {
         gState = 0;
         currentState = 0;
 
         llSetTimerEvent (TIMER_INTERVAL);
         llSetTimerEvent (TIMER_INTERVAL);
     }
     }
   
 
     timer ()
     timer ()
     {
     {
         gState ++;
         ++currentState;// ++index is faster than index++
         if (gState == 1)
 
         if (currentState == 1)
         {
         {
             // Do the first thing here
             // Do the first thing here
         }
         }
         else if (gState == 2)
         else if (currentState == 2)
         {
         {
             // After the timer interval this is next
             // After the timer interval this is next
         }
         }
         else if (gState == 3)
         else if (currentState == 3)
         {
         {
             // and the next
             // and the next
Line 251: Line 262:
         {
         {
             // Once all states are complete, reset the counter ready for the next time
             // Once all states are complete, reset the counter ready for the next time
             gState = 0;
             currentState = 0;
         }
         }
     }
     }
Line 264: Line 275:
// Kimm Paulino, Oct 2012
// Kimm Paulino, Oct 2012


key     gNCQueryId;
key     notecardQueryId;
integer gNCLine;
integer notecardLine;
integer gNCNumber;
integer notecardNumber;
string   gNCName;
string notecardName;


default
default
Line 275: Line 286:
         llResetScript();
         llResetScript();
     }
     }
      
 
     changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
 
     state_entry ()
     state_entry ()
     {
     {
         gNCNumber = 0;
         notecardNumber = 0;
         gNCLine = 0;
         notecardLine = 0;
         gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber);
 
         if (gNCName != "")
         notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardNumber);
         if (notecardName != "")
         {
         {
             llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")");
             llOwnerSay("=== Reading notecard '" + notecardName + "' (" + (string)notecardNumber + ")");
             gNCQueryId = llGetNotecardLine (gNCName, gNCLine);
             notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
         }
         }
     }
     }
   
 
     dataserver (key query_id, string data)
     dataserver (key query_id, string data)
     {
     {
         if (query_id != gNCQueryId)
         if (query_id != notecardQueryId)
         {
         {
            // Not for us
        // Not for us
             return;
             return;
         }
         }
Line 302: Line 322:
         {
         {
             // Move to the next notecard
             // Move to the next notecard
             gNCNumber++;
             ++notecardNumber;
             gNCLine = 0;
             notecardLine = 0;
             gNCName = llGetInventoryName (INVENTORY_NOTECARD, gNCNumber);
 
             if (gNCName != "")
             notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardNumber);
             if (notecardName != "")
             {
             {
                 llOwnerSay ("=== Reading notecard " + gNCName + " (" + (string)gNCNumber + ")");
                 llOwnerSay("=== Reading notecard '" + notecardName + "' (" + (string)notecardNumber + ")");
                 gNCQueryId = llGetNotecardLine (gNCName, gNCLine);
                 notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
             }
             }
             else
             else
Line 322: Line 343:
         // Note: Only get first 255 characters of each line
         // Note: Only get first 255 characters of each line
         llOwnerSay (data);
         llOwnerSay (data);
       
 
         // and read the next line
         // and read the next line
         gNCLine++;
         ++notecardLine;
         gNCQueryId = llGetNotecardLine(gNCName, gNCLine);
         notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
    }
   
    changed (integer change)
    {
        if (change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
     }
     }
}
}
Line 348: Line 361:
// Uses 24 hour times
// Uses 24 hour times
// Can include touch control if required
// Can include touch control if required
// Sends the specified message to the specified UUID  
// Sends the specified message to the specified UUID
//
//
// If you want it to do something else, code it in the alarm() function
// If you want it to do something else, code it in the alarm() function
Line 359: Line 372:
integer gMin = 30;
integer gMin = 30;
integer gSec = 0;
integer gSec = 0;
integer gGMT = TRUE;  // GMT or SL time
integer isGMTnotSL = TRUE;  // GMT or SL time
integer gTouchControl = TRUE;
integer gTouchControl = TRUE;
string gMsg = "Wake up!";
string alarmMessage = "Wake up!";
key gAv = "00000000-0000-0000-0000-000000000000";
 
//  NULL_KEY has the key value "00000000-0000-0000-0000-000000000000"
key avatarToBeAlarmed = NULL_KEY;


integer gArmed;
integer alarmIsArmed;


setAlarm ()
setAlarm ()
Line 374: Line 389:
     // so the required setting until the destination time
     // so the required setting until the destination time
     // will depend on if the time is in the past or not.
     // will depend on if the time is in the past or not.
     // If we happen to get lucky and  
     // If we happen to get lucky and
     float nowtime = llGetWallclock ();
     float nowtime = llGetWallclock();
     if (gGMT)
     if (isGMTnotSL)
     {
     {
         nowtime = llGetGMTclock ();
         nowtime = llGetGMTclock();
     }
     }
   
 
     if (nowtime >= desttime)
     if (nowtime >= desttime)
     {
     {
         // Need to add 24 hours before subtracting
         // Need to add 24 hours before subtracting
         desttime = desttime + 24.0*60.0*60.0;
         desttime = desttime + 24.0*60.0*60.0;
         llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime);
         llOwnerSay("Dest: " + (string)desttime + " Now: " + (string)nowtime);
         llSetTimerEvent (desttime - nowtime);
         llSetTimerEvent(desttime - nowtime);
     }
     }
     else
     else
     {
     {
         llOwnerSay ("Dest: " + (string)desttime + " Now: " + (string)nowtime);
         llOwnerSay("Dest: " + (string)desttime + " Now: " + (string)nowtime);
         llSetTimerEvent (desttime - nowtime);
         llSetTimerEvent(desttime - nowtime);
     }
     }
}
}
Line 397: Line 412:
disableAlarm()
disableAlarm()
{
{
     llSetTimerEvent (0.0);
     llSetTimerEvent((float)FALSE);
}
}


Line 403: Line 418:
alarm ()
alarm ()
{
{
     //llOwnerSay ("Alarm");
     //llOwnerSay("Alarm");
     llInstantMessage (gAv, gMsg);
     llInstantMessage(avatarToBeAlarmed, alarmMessage);
}
}


Line 412: Line 427:
     {
     {
         string zone = " SLT";
         string zone = " SLT";
         if (gGMT)
         if (isGMTnotSL)
         {
         {
             zone = " GMT";
             zone = " GMT";
         }
         }
         llOwnerSay ("Alarm set for " + (string)gHour + " h " + (string)gMin + " m" + (string)gSec + " s " + zone);
         llOwnerSay("Alarm set for " + (string)gHour + " h " + (string)gMin + " m" + (string)gSec + " s " + zone);
         gArmed = TRUE;
         alarmIsArmed = TRUE;
         setAlarm();
         setAlarm();
     }
     }
   
 
     touch_start (integer num_detected)
     touch_start (integer num_detected)
     {
     {
         if (gTouchControl)
         if (gTouchControl)
         {
         {
             if (gArmed)
             if (alarmIsArmed)
             {
             {
                 gArmed = FALSE;
                 alarmIsArmed = FALSE;
                 disableAlarm();
                 disableAlarm();
             }
             }
             else
             else
             {
             {
                 gArmed = TRUE;
                 alarmIsArmed = TRUE;
                 setAlarm();
                 setAlarm();
             }
             }
         }
         }
     }
     }
   
 
     timer ()
     timer ()
     {
     {
         alarm();
         alarm();
        // Reset alarm each time, to allow for any drift in time
 
    // Reset alarm each time, to allow for any drift in time
         setAlarm();
         setAlarm();
     }
     }
}
}
</lsl>
</lsl>

Revision as of 15:12, 22 October 2012

Rez and Sense

<lsl> // Rezzer that will only rez an object (from inventory) if it // can't detect the specified number of objects in the region nearby already. // // Note: Sensing is limitd to a maximum of 96m in all directions. If the // objects pass out of that range, this won't find them. // // Always looks for (and rezzes) the first object found in inventory. // NB: This must have copy permissions if you want to rez it more than once! // // Kimm Paulino, July 2012

integer MAX_REZZED_OBJECTS = 5; vector REZ_POSITION = <1.0, 0.0, 0.0>; // Relative to the rezzing prim, must be less than 10m away vector REZ_ROTATION = ZERO_VECTOR; // In degrees

string objectName;

rezObject () {

   vector currentPosition = llGetPos();
   llRezObject (gObjectName, currentPosition + REZ_POSITION, ZERO_VECTOR, llEuler2Rot (REZ_ROTATION * DEG_TO_RAD), 0);

}

default {

   on_rez (integer start_param)
   {
       llResetScript();
   }
   changed (integer change)
   {
       if (change & CHANGED_INVENTORY)
       {
           llResetScript();
       }
   }
   state_entry ()
   {
       objectName = llGetInventoryName (INVENTORY_OBJECT, 0);
       if (objectName == "")
       {
           llOwnerSay ("Note to owner: No objects found in this prims inventory");
       }
   }
   touch_start (integer num_detected)
   {
       if (gObjectName != "")
       {
       //  Trigger a single sensor event for the full range/arc looking for any non-avatar
       //  objects with the same name as our rezzing object.
           llSensor (gObjectName, NULL_KEY, (ACTIVE|PASSIVE), 96.0, PI);
       }
   }
   sensor (integer num_detected)
   {
       if (num_detected < MAX_REZZED_OBJECTS)
       {
           rezObject();
       }
       else
       {
       //  Nothing to do
           llOwnerSay ("Max Objects detected ...");
       }
   }
   no_sensor ()
   {
       // None found, so ok to rez one
       rezObject();
   }

} </lsl>

Derez After Sitting

<lsl> // This will kill the prim it is in, the specified time after someone // sits on the prim. It will unsit them before derezzing. // // Note: This only works when the prim has a sittarget defined. // But this script does not have to be the thing setting it, // if the sit target is set to <0.0,0.0,0.0> in this script, // then no call to llSitTarget is made - so another script // can do it instead. // // It can optionally derez on unsit too - i.e. when they get up // or derez a defined time after they unsit. // // Note: It doesn't unsit any other avatars sitting on other // prims prior to derezzing, but derezzing will unsit them anyway! // // It will also (optionally) automatically derez itself after a specified // time if noone sits down on it. // // Kimm Paulino, July 2012

// TRUE if want to immediately auto derez when av gets up. // (overrides DEREZ_AFTER_UNSIT_TIMEOUT) integer DEREZ_ON_UNSIT = FALSE;

// Time to derez if noone sits down // (in seconds - 0.0 to disable) float DEREZ_TIMEOUT = 60.0;

// Once an av sits down, this timer starts // and will derez when it times out. // (in seconds - 0.0 to disable) float DEREZ_AFTER_SIT_TIMEOUT = 30.0;

// Once an av gets up, this timer starts // and will derez when it times out. // (in seconds - 0.0 to disable) float DEREZ_AFTER_UNSIT_TIMEOUT = 0.0;

// Position of the sittarget vector SIT_VECTOR = <0.0, 0.0, 0.5>; // In metres - ZERO_VECTOR to disable vector SIT_ROTATION = ZERO_VECTOR; // In degrees

key avatarOnSitTarget; integer isSitting = FALSE;

default {

   on_rez (integer start_param)
   {
       llResetScript();
   }
   changed (integer change)
   {
   //  When someone sits on an object, the av is considered to be
   //  a linked-in child prim, so the link number changes
       if (change & CHANGED_LINK)
       {
           avatarOnSitTarget = llAvatarOnSitTarget();
           if (avatarOnSitTarget)
           {
           //  Avatar has just sat down
               isSitting = TRUE;
               llSetTimerEvent(DEREZ_AFTER_SIT_TIMEOUT);
           }
           else if (isSitting)
           {
           //  Assume av just got up - it was sitting and now isn't ...
               isSitting = FALSE;
               if (DEREZ_ON_UNSIT)
               {
               //  Want to derez straight away
                   llDie();
               }
               llSetTimerEvent(DEREZ_AFTER_UNSIT_TIMEOUT);
           }
           else
           {
               // Could be unlinking going on
               // or maybe there is another sit target in a linked prim
               // that someone has just sat on or vacated
           }
       }
   }
   state_entry()
   {
       if (SIT_VECTOR != ZERO_VECTOR)
       {
           llSitTarget(SIT_VECTOR, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD));
       }
       llSetTimerEvent(DEREZ_TIMEOUT);
   }
   timer ()
   {
       if (avatarOnSitTarget)
       {
           llUnSit(avatarOnSitTarget);
       }
       llSetTimerEvent((float)FALSE);//  disable timer
       llDie();
   }

} </lsl>

Timer Action Template

<lsl> // Basic timer-driven state changing script. // NB: Does not use the LSL ability to define // states, but uses a counter to manage a simple // incrementing state machine. // // Every time interval, it will change its record of state // and you can add code to do something, then it will move // to the next state. // // To add more things, just add more // else if (currentState == 4) // { // // and the next // } // statements in the appropriate place. // // If you want the timer interval to be different for different // states, then you could add more llSetTimerEvent() calls // in each state to set the timer for the next one. // // Kimm Paulino // Sept 2012

// Timer interval in seconds float TIMER_INTERVAL = 5.0;

integer currentState;

default {

   on_rez (integer start_param)
   {
       llResetScript();
   }
   state_entry ()
   {
       currentState = 0;
       llSetTimerEvent (TIMER_INTERVAL);
   }
   timer ()
   {
       ++currentState;// ++index is faster than index++
       if (currentState == 1)
       {
           // Do the first thing here
       }
       else if (currentState == 2)
       {
           // After the timer interval this is next
       }
       else if (currentState == 3)
       {
           // and the next
       }
       // add more else if () statements here
       else
       {
           // Once all states are complete, reset the counter ready for the next time
           currentState = 0;
       }
   }

} </lsl>

Multiple Notecard Reading Template

<lsl> // Example showing multiple notecard reading. // // Kimm Paulino, Oct 2012

key notecardQueryId; integer notecardLine; integer notecardNumber; string notecardName;

default {

   on_rez (integer start_param)
   {
       llResetScript();
   }
   changed (integer change)
   {
       if (change & CHANGED_INVENTORY)
       {
           llResetScript();
       }
   }
   state_entry ()
   {
       notecardNumber = 0;
       notecardLine = 0;
       notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardNumber);
       if (notecardName != "")
       {
           llOwnerSay("=== Reading notecard '" + notecardName + "' (" + (string)notecardNumber + ")");
           notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
       }
   }
   dataserver (key query_id, string data)
   {
       if (query_id != notecardQueryId)
       {
       //  Not for us
           return;
       }
       // Note: If the notecard contains embedded objects (like scripts, landmarks, etc)
       // then EOF is returned - so this will move onto the next one as if the notecard
       // was empty.
       if (data == EOF)
       {
           // Move to the next notecard
           ++notecardNumber;
           notecardLine = 0;
           notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardNumber);
           if (notecardName != "")
           {
               llOwnerSay("=== Reading notecard '" + notecardName + "' (" + (string)notecardNumber + ")");
               notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
           }
           else
           {
               llOwnerSay ("=== Complete");
           }
           // Wait for the next line to be read
           return;
       }
       // Do something with the notecard line
       // Note: Only get first 255 characters of each line
       llOwnerSay (data);
       // and read the next line
       ++notecardLine;
       notecardQueryId = llGetNotecardLine(notecardName, notecardLine);
   }

} </lsl>

Alarm Script

<lsl> // Simple script to trigger at a certain time and perform a function, // in the default case send an IM to the specified avatar // // Notes // Can specify a time in GMT (ie no seasonal changes) or SLT // Uses 24 hour times // Can include touch control if required // Sends the specified message to the specified UUID // // If you want it to do something else, code it in the alarm() function // // Kimm Paulino // Oct 2012 // http://kimmscripts.wordpress.com/

integer gHour = 7; // 24 hour clock integer gMin = 30; integer gSec = 0; integer isGMTnotSL = TRUE; // GMT or SL time integer gTouchControl = TRUE; string alarmMessage = "Wake up!";

// NULL_KEY has the key value "00000000-0000-0000-0000-000000000000" key avatarToBeAlarmed = NULL_KEY;

integer alarmIsArmed;

setAlarm () {

   // set a timer event for destination time - current time
   float desttime = (float)(gHour*60*60 + gMin*60 + gSec);
   // This is the number of seconds since midnight
   // so the required setting until the destination time
   // will depend on if the time is in the past or not.
   // If we happen to get lucky and
   float nowtime = llGetWallclock();
   if (isGMTnotSL)
   {
       nowtime = llGetGMTclock();
   }
   if (nowtime >= desttime)
   {
       // Need to add 24 hours before subtracting
       desttime = desttime + 24.0*60.0*60.0;
       llOwnerSay("Dest: " + (string)desttime + " Now: " + (string)nowtime);
       llSetTimerEvent(desttime - nowtime);
   }
   else
   {
       llOwnerSay("Dest: " + (string)desttime + " Now: " + (string)nowtime);
       llSetTimerEvent(desttime - nowtime);
   }

}

disableAlarm() {

   llSetTimerEvent((float)FALSE);

}

// This is what happens on the alarm alarm () {

   //llOwnerSay("Alarm");
   llInstantMessage(avatarToBeAlarmed, alarmMessage);

}

default {

   state_entry()
   {
       string zone = " SLT";
       if (isGMTnotSL)
       {
           zone = " GMT";
       }
       llOwnerSay("Alarm set for " + (string)gHour + " h " + (string)gMin + " m" + (string)gSec + " s " + zone);
       alarmIsArmed = TRUE;
       setAlarm();
   }
   touch_start (integer num_detected)
   {
       if (gTouchControl)
       {
           if (alarmIsArmed)
           {
               alarmIsArmed = FALSE;
               disableAlarm();
           }
           else
           {
               alarmIsArmed = TRUE;
               setAlarm();
           }
       }
   }
   timer ()
   {
       alarm();
   //  Reset alarm each time, to allow for any drift in time
       setAlarm();
   }

} </lsl>