Allen Kerensky"It seems you've been living two lives ..."

Myriad Lite Module RLV

// Myriad_Lite_Module_RLV-v0.0.0-20131024.lsl
// Copyright (c) 2013 by Allen Kerensky (OSG/SL) All Rights Reserved.
// This work is dual-licensed under
// Creative Commons Attribution (CC BY) 3.0 Unported
// http://creativecommons.org/licenses/by/3.0/
// - or -
// Modified BSD License (3-clause)
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, 
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of Myriad Lite nor the names of its contributors may be
//   used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
// NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Myriad RPG System was designed, written, and illustrated by Ashok Desai
// Myriad RPG System licensed under:
// Creative Commons Attribution (CC BY) 2.0 UK: England and Wales
// http://creativecommons.org/licenses/by/2.0/uk/
 
// SEE: http://wiki.secondlife.com/wiki/LSL_Protocol/RestrainedLoveAPI
    // RLV_VERSIONNUM();
    // ... more setup functions here
    // RLV Functions http://wiki.secondlife.com/wiki/LSL_Protocol/RestrainedLoveAPI
    // LOAD current from PPMA
    // -- VERSIONS
    // Automated version @version=<channel>
    // RPG: Automated version @versionnew=<channel>
    // RPG: Automated version @versionnum=<channel>
    // Manual version IM @version
    // --- BLACKLIST
    // Automated version followed by blacklist: @versionnumbl=<channel>
    // Get contents of the blacklist with filter: @getblacklist[:filter]=<channel>
    // Manual blacklist checking: IM @getblacklist
    // --- MISCELLANEOUS
    // Start/stop notifications on a private channel: @notify:<channel>[;word]=<rem/add>
    //      /accepted_in_rlv inv_offer <folder> accepted and available under #RLV/
    //      /accepted_in_inv inv_offer <folder> accepted but not shared
    //      /declined inv_offer <folder> 
    //      /worn legally <layer>
    //      /unworn legally <layer>
    //      /attached legally <attach_point_name>
    //      /attached illegally <attach_point_name>
    //      /detached legally <attach_point_name>
    //      /detached illegally <attach_point_name>
    // Allow/deny permissive exceptions: @permissive=y/n RLV,PERMISSIVE,y/n
    // Clear all rules tied to an object: @clear
    // Clear a subset of the rules tied to an object: @clear=<string>
    // RPG: Get the list of restrictions the avatar is currently submitted to: @getstatus[:<part_of_rule>[;<custom_separator>]]=<channel>
    // Get the list of ALL restrictions the avatar is currently submitted to: @getstatusall[:<part_of_rule>[;<custom_separator>]]=<channel>
    // --- MOVEMENT
    // RPG: Allow/prevent flying @fly=<y/n>
    // Allow/prevent run by double-tap an arrow: @temprun=<y/n>
    // RPG: Allow/prevent always running: @alwaysrun=<y/n>
    // Force rotate the avatar to a set direction: @setrot=<angle_in_radians>=force
    // BROKEN w/SSA Change the height of the avatar: @adjustheight:<distance_pelvis_to_foot_in_meters>;<factor>[;delta_in_meters]=force
    // --- CHAT
    // Allow/prevent sending chat: @sendchat=<y/n> - blocks channel 0, / works, /me 30 chars, /message 15 chars, punctuation blocked, . ends the string
    // Allow/prevent shouting: @chatshout=<y/n> - forces llShout to llSay range
    // Allow/prevent chatting at normal volume: @chatnormal=<y/n> - forces llSay to llWhisper range
    // Allow/prevent whispering: @chatwhisper=<y/n> - force whisper to llSay range
    // RPG: Redirect public chat to private channels: @redirchat:<channel>=<rem/add> -- turn ON OFF with Emoter control
    // Allow/prevent receiving chat messages : "@recvchat=<y/n>" 
    // Allow/prevent receiving chat messages, secure way : "@recvchat_sec=<y/n>" 
    // Remove/add exceptions to the chat message receiving prevention : "@recvchat:<UUID>=<rem/add>"
    // Allow/prevent receiving chat messages from someone in particular : "@recvchatfrom:<UUID>=<y/n>"
    // --- EMOTES
    // Remove/add an exception to the emote truncation above : "@emote=<rem/add>" 
    // Redirect public emotes to private channels : "@rediremote:<channel_number>=<rem/add>" 
    // Allow/prevent seeing emotes : "@recvemote=<y/n>" 
    // Allow/prevent receiving emotes seen in public chat from someone in particular : "@recvemotefrom:<UUID>=<y/n>" 
    // Allow/prevent seeing emotes, secure way : "@recvemote_sec=<y/n>" 
    // Remove/add exceptions to the emote seeing prevention : "@recvemote:<UUID>=<rem/add>"
    // --- PRIVATE CHANNELS
    // RPG: Allow/prevent using any chat channel but certain channels : @sendchannel[:<channel>]=<y/n> - only allow Myriad channels
    // RPG: Allow/prevent using any chat channel but certain channels, secure way : @sendchannel_sec[:<channel>]=<y/n>
    // --- INSTANT MESSAGES 
    // RPG: Allow/prevent sending instant messages : "@sendim=<y/n>" 
    // RPG: Allow/prevent sending instant messages, secure way : "@sendim_sec=<y/n>" 
    // Remove/add exceptions to the instant message sending prevention : "@sendim:<UUID>=<rem/add>" 
    // RPG: Allow/prevent sending instant messages to someone in particular : "@sendimto:<UUID>=<y/n>" - allow to region staff
    // Allow/prevent starting an IM session with anyone : "@startim=<y/n>" 
    // Remove/add exceptions to the IM session start prevention : "@startim:<UUID>=<rem/add>" 
    // RPG: Allow/prevent starting an IM session with someone in particular : "@startimto:<UUID>=<y/n>" -- allow to region staff
    // RPG: Allow/prevent receiving instant messages : "@recvim=<y/n>" 
    // RPG: Allow/prevent receiving instant messages, secure way : "@recvim_sec=<y/n>"
    // Remove/add exceptions to the instant message receiving prevention : "@recvim:<UUID>=<rem/add>" 
    // RPG: Allow/prevent receiving instant messages from someone in particular : "@recvimfrom:<UUID>=<y/n>"  - allow from Region staff
    // --- TELEPORT
    // RPG: Allow/prevent teleporting to a landmark : "@tplm=<y/n>"  - enable TP in OOC, disable in IC
    // RPG: Allow/prevent teleporting to a location : "@tploc=<y/n>" - enable TP in OOC, disable in IC
    // RPG: Allow/prevent teleporting by a friend : "@tplure=<y/n>" 
    // RPG: Allow/prevent teleporting by a friend, secure way : "@tplure_sec=<y/n>"
    // Remove/add exceptions to the friend teleport prevention : "@tplure:<UUID>=<rem/add>"
    // RPG: Unlimit/limit sit-tp : "@sittp=<y/n>"
    // RPG: Allow/prevent standing up at a different location than where we sat down : @standtp=<y/n> 
    // Force-Teleport the user : @tpto:<X>/<Y>/<Z>=force (*)
    // RPG: Remove/add auto-accept teleport offers from a particular avatar : "@accepttp[:<UUID>]=<rem/add>" -- region owner and RPG staff?
    // --- INVENTORY
    // RPG: Allow/prevent using inventory : @showinv=<y/n>
    // RPG: Allow/prevent reading notecards : @viewnote=<y/n>
    // RPG: Allow/prevent opening scripts : @viewscript=<y/n> 
    // RPG: Allow/prevent opening textures : @viewtexture=<y/n> 
    // RPG: Allow/prevent editing objects : "@edit=<y/n>" 
    // Remove/add exceptions to the edit prevention : "@edit:<UUID>=<rem/add>" 
    // RPG: Allow/prevent rezzing inventory : "@rez=<y/n>" 
    // Allow/prevent editing particular objects : "@editobj:<UUID>=<y/n>" 
    // --- SITTING
    // Allow/prevent standing up : @unsit=<y/n> 
    // Force sit on an object : @sit:<UUID>=force (*) 
    // Get the UUID of the object the avatar is sitting on : @getsitid=<channel_number> 
    // Force unsit : @unsit=force (*)
    // Allow/prevent sitting down : @sit=<y/n> 
    // --- CLOTHING
    // Render an object detachable/nondetachable : "@detach=<y/n>" 
    // Unlock/Lock an attachment point : "@detach:<attach_point_name>=<y/n>" 
    // Unlock/Lock an attachment point empty : "@addattach[:<attach_point_name>]=<y/n>" 
    // Unlock/Lock an attachment point full : "@remattach[:<attach_point_name>]=<y/n>" 
    // Allow/deny the "Wear" contextual menu : "@defaultwear=<y/n> 
    // Force removing attachments : @detach[:attachpt]=force (*) 
    //      chest|skull|left shoulder|right shoulder|left hand|right hand|left foot|right foot|spine|
    //      pelvis|mouth|chin|left ear|right ear|left eyeball|right eyeball|nose|r upper arm|r forearm|
    //      l upper arm|l forearm|right hip|r upper leg|r lower leg|left hip|l upper leg|l lower leg|stomach|left pec|
    //      right pec|center 2|top right|top|top left|center|bottom left|bottom|bottom right|neck|root
    //      If part is not specified, removes everything. 
    // Force removing attachments (alias) : @remattach[:attachpt]=force (*) 
    // Allow/prevent wearing clothes : @addoutfit[:<part>]=<y/n> 
    //       gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|skin|eyes|hair|shape|alpha|tattoo|physics
    //       If part is not specified, prevents from wearing anything beyond what the avatar is already wearing. 
    // Allow/prevent removing clothes : @remoutfit[:<part>]=<y/n> (underpants and undershirt are kept for teens) 
    //      gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|skin|eyes|hair|shape|alpha|tattoo|physics
    //      If part is not specified, prevents from removing anything in what the avatar is wearing
    // Force removing clothes : @remoutfit[:<part>]=force (*) (teens can't be forced to remove underpants and undershirt)
    //      gloves|jacket|pants|shirt|shoes|skirt|socks|underpants|undershirt|alpha|tattoo|physics
    //      If part is not specified, removes everything. 
    // Get the list of worn clothes : @getoutfit[:part]=<channel_number> 
    //      gloves,jacket,pants,shirt,shoes,skirt,socks,underpants,undershirt,skin,eyes,hair,shape
    //      gloves,jacket,pants,shirt,shoes,skirt,socks,underpants,undershirt,skin,eyes,hair,shape,alpha,tattoo 
    // Get the list of worn attachments : @getattach[:attachpt]=<channel_number> 
    //     none,chest,skull,left shoulder,right shoulder,left hand,right hand,left foot,right foot,spine,
    //     pelvis,mouth,chin,left ear,right ear,left eyeball,right eyeball,nose,r upper arm,r forearm,
    //     l upper arm,l forearm,right hip,r upper leg,r lower leg,left hip,l upper leg,l lower leg,stomach,left pec,
    //     right pec,center 2,top right,top,top left,center,bottom left,bottom,bottom right,neck,root
    // Force the viewer to automatically accept attach and take control permission requests : @acceptpermission=<rem/add> 
    // Allow/prevent accepting attach and take control permissions : @denypermission=<rem/add> 
    // Force detach an item : @detachme=force (*) 
    // --- SHARED FOLDERS
    // Allow/prevent wearing clothes and attachments that are not part of the #RLV folder : @unsharedwear=<y/n> 
    // Allow/prevent removing clothes and attachments that are not part of the #RLV folder : @unsharedunwear=<y/n> 
    // Get the list of shared folders in the avatar's inventory : @getinv[:folder1/.../folderN]=<channel_number> 
    // Get the list of shared folders in the avatar's inventory, with information about worn items : @getinvworn[:folder1/.../folderN]=<channel_number> 
    // Get the path to a shared folder by giving a search criterion : @findfolder:part1[&&...&&partN]=<channel_number> 
    // Force attach items contained inside a shared folder : @attach:<folder1/.../folderN>=force (*) 
    // Force attach items contained inside a shared folder, without replacing what is already being worn : @attachover:<folder1/.../folderN>=force (*) 
    // Force attach items contained inside a shared folder : @attachoverorreplace:<folder1/.../folderN>=force (*) 
    // Force attach items contained inside a shared folder, and its children recursively : @attachall:<folder1/.../folderN>=force (*) 
    // Force attach items contained inside a shared folder, and its children recursively, without replacing what is already being worn : @attachallover:<folder1/.../folderN>=force (*) 
    // Force attach items contained inside a shared folder, and its children recursively : @attachalloverorreplace:<folder1/.../folderN>=force (*) 
    // Force detach items contained inside a shared folder : @detach:<folder_name>=force (*) 
    // Force detach items contained inside a shared folder, and its children recursively : @detachall:<folder1/.../folderN>=force (*) 
    // Get the path to the shared folder containing a particular object/clothing worn on a point : @getpath[:<attachpt> or <clothing_layer>]=<channel_number> 
    // Get the all paths to the shared folders containing the objects/clothing worn on a point : @getpathnew[:<attachpt> or <clothing_layer>]=<channel_number> 
    // Force attach items contained into a shared folder that contains a particular object/clothing : @attachthis[:<attachpt> or <clothing_layer>]=force (*) 
    // Force attach items contained inside a shared folder, without replacing what is already being worn : @attachthisover[:<attachpt> or <clothing_layer>]=force (*) 
    // Force attach items contained inside a shared folder : @attachthisoverorreplace[:<attachpt> or <clothing_layer>]=force (*) 
    // Force attach items contained into a shared folder that contains a particular object/clothing, and its children folders : @attachallthis[:<attachpt> or <clothing_layer>]=force (*) 
    // Force attach items contained inside a shared folder, without replacing what is already being worn : @attachallthisover[:<attachpt> or <clothing_layer>]=force (*) 
    // Force attach items contained inside a shared folder : @attachallthisoverorreplace[:<attachpt> or <clothing_layer>]=force (*) 
    // Force detach items contained into a shared folder that contains a particular object/clothing : @detachthis[:<attachpt> or <clothing_layer>]=force (*) 
    // Force detach items contained into a shared folder that contains a particular object/clothing, and its children folders : @detachallthis[:<attachpt> or <clothing_layer>]=force (*) 
    // Allow/prevent removing some folders : @detachthis[:<layer>|<attachpt>|<path_to_folder>]=<y/n> 
    // Allow/prevent removing some folders and their children : @detachallthis[:<layer>|<attachpt>|<path_to_folder>]=<y/n> 
    // Allow/prevent wearing some folders : @attachthis:<layer>|<attachpt>|<path_to_folder>=<y/n> 
    // Allow/prevent wearing some folders and their children : @attachallthis[:<layer>|<attachpt>|<path_to_folder>]=<y/n> 
    // Remove/add exceptions to the detachallthis restriction, for one folder only : "@detachthis_except:<folder>=<rem/add>" 
    // Remove/add exceptions to the detachallthis restriction, for one folder and its children : "@detachallthis_except:<folder>=<rem/add>" 
    // Remove/add exceptions to the attachallthis restriction, for one folder only : "@attachthis_except:<folder>=<rem/add>" 
    // Remove/add exceptions to the attachallthis restriction, for one folder and its children : "@attachallthis_except:<folder>=<rem/add>" 
    // --- TOUCH
    // RPG: Allow/prevent touching objects located further than 1.5 meters away from the avatar : @fartouch=<y/n> 
    // Allow/prevent touching objects located further than 1.5 meters away from the avatar : @touchfar=<y/n> 
    // Allow/prevent touching any objects : @touchall=<y/n> 
    // Allow/prevent touching objects in-world : @touchworld=<y/n> 
    // Remove/add exceptions to the touchworld prevention : "@touchworld:<UUID>=<rem/add>" 
    // Allow/prevent touching one object in particular : @touchthis:<UUID>=<rem/add> 
    // Remove/add an exception to the touch* preventions, for one object only : "@touchme=<rem/add>" 
    // Allow/prevent touching attachments : @touchattach=<y/n> 
    // Allow/prevent touching one's attachments : @touchattachself=<y/n> 
    // ???: Allow/prevent touching other people's attachments : @touchattachother=<y/n>  
    // --- LOCATION
    // RPG: Allow/prevent viewing the world map : @showworldmap=<y/n>  -- only allow when holding MAP item
    // RPG: Allow/prevent viewing the mini map : @showminimap=<y/n> -- only allow when holding SCANNER item
    // RPG: Allow/prevent knowing the current location : @showloc=<y/n> 
    // --- NAME TAGS
    // RPG: Allow/prevent seeing the names of the people around : @shownames=<y/n> 
    // RPG: Allow/prevent seeing all the hovertexts : @showhovertextall=<y/n> 
    // RPG: Allow/prevent seeing one hovertext in particular : @showhovertext:<UUID>=<y/n>  -- allow see region owner and staff?
    // RPG: Allow/prevent seeing the hovertexts on the HUD of the user : @showhovertexthud=<y/n> 
    // RPG: Allow/prevent seeing the hovertexts in-world : @showhovertextworld=<y/n> 
    // --- GROUP
    // RPG: Force the agent to change the active group : @setgroup:<group_name>=force 
    // RPG: Allow/prevent activating a group : @setgroup=<y/n> 
    // Get the name of the active group : @getgroup=<channel_number> 
    // --- VIEWER
    // Allow/prevent changing some debug settings : @setdebug=<y/n> 
    // Force change a debug setting : @setdebug_<setting>:<value>=force (*) 
    // Get the value of a debug setting : @getdebug_<setting>=<channel_number>
    // RPG: Allow/prevent changing the environment settings : @setenv=<y/n>      
    // Allow/prevent changing the environment settings : @setenv=<y/n> 
    // RPG: Force change an environment setting : @setenv_<setting>:<value>=force (*) -- set world, drug effects, incapacitated and dead effects and more
    //     _daytime     0.0-1.0 and <0     Time of day (sunrise:0.25, midday:0.567, sunset:0.75, midnight:0.0, set back to region default:<0). Attention, resets all other Windlight parameters
    //     _preset     String     A Preset environment, e.g. Gelatto, Foggy. Attention, loading a Preset is heavy on the viewer and can slow it down for a short while, don't do it every second
    //     _ambientr     0.0-1.0     Ambient light, Red channel
    //     _ambientg     0.0-1.0     Ambient light, Green channel
    //     _ambientb     0.0-1.0     Ambient light, Blue channel
    //     _ambienti     0.0-1.0     Ambient light, Intensity
    //     _bluedensityr     0.0-1.0     Blue Density, Red channel
    //     _bluedensityg     0.0-1.0     Blue Density, Green channel
    //     _bluedensityb     0.0-1.0     Blue Density, Blue channel
    //     _bluedensityi     0.0-1.0     Blue Density, Intensity
    //     _bluehorizonr     0.0-1.0     Blue Horizon, Red channel
    //     _bluehorizong     0.0-1.0     Blue Horizon, Green channel
    //     _bluehorizonb     0.0-1.0     Blue Horizon, Blue channel
    //     _bluehorizoni     0.0-1.0     Blue Horizon, Intensity
    //     _cloudcolorr     0.0-1.0     Cloud color, Red channel
    //     _cloudcolorg     0.0-1.0     Cloud color, Green channel
    //     _cloudcolorb     0.0-1.0     Cloud color, Blue channel
    //     _cloudcolori     0.0-1.0     Cloud color, Intensity
    //     _cloudcoverage     0.0-1.0     Cloud coverage
    //     _cloudx     0.0-1.0     Cloud offset X
    //     _cloudy     0.0-1.0     Cloud offset Y
    //     _cloudd     0.0-1.0     Cloud density
    //     _clouddetailx     0.0-1.0     Cloud detail X
    //     _clouddetaily     0.0-1.0     Cloud detail Y
    //     _clouddetaild     0.0-1.0     Cloud detail density
    //     _cloudscale     0.0-1.0     Cloud scale
    //     _cloudscrollx     0.0-1.0     Cloud scroll X
    //     _cloudscrolly     0.0-1.0     Cloud scroll Y
    //     _densitymultiplier     0.0-0.9     Density multiplier of the fog
    //     _distancemultiplier     0.0-100.0     Distance multiplier of the fog
    //     _eastangle     0.0-1.0     Position of the east, 0.0 is normal
    //     _hazedensity     0.0-1.0     Density of the haze
    //     _hazehorizon     0.0-1.0     Haze at the horizon
    //     _maxaltitude     0.0-4000.0     Maximum altitude of the fog
    //     _scenegamma     0.0-10.0     Overall gamma, 1.0 is normal
    //     _starbrightness    0.0-2.0     Brightness of the stars
    //     _sunglowfocus     0.0-0.5     Focus of the glow of the sun
    //     _sunglowsize     1.0-2.0     Size of the glow of the sun
    //     _sunmooncolorr     0.0-1.0     Sun and moon, Red channel
    //     _sunmooncolorg     0.0-1.0     Sun and moon, Green channel
    //     _sunmooncolorb     0.0-1.0     Sun and moon, Blue channel
    //     _sunmooncolori     0.0-1.0     Sun and moon, Intensity
    //     _sunmoonposition     0.0-1.0     Position of the sun/moon, different from "daytime", use this to set the apparent sunlight after loading a Preset
    // Get the value of an environment setting : @getenv_<setting>=<channel_number> 
 
// CONSTANTS - DO NOT CHANGE DURING RUN
string BASENAME = "Myriad Lite Module RLV";
string VERSION = "0.0.0"; // Allen Kerensky's script version
string VERSIONDATE = "20131024"; // Allen Kerensky's script yyyymmdd
 
// Module to Module Messaging Constants
integer MODULE_RLV = -15;
integer LM_SENDTOATTACHMENT = 0x80000000;
 
// Configurable
integer SPACE_OFFSET = 300; // How high over ground are we to be "in space" FIXME PPMA CONFIG,SPACEALTITIDE,<meters>
 
// Runtime globals - may change anytime during run
integer RLV_CHAN;
integer RLV_HAND;
string RLV_CMD;
integer RLV_AVAIL; // is RLV available?
vector CURPOS; // current X,Y,Z location of avatar
integer GROUND_LEVEL; // the current Z altitude of ground level under the av.
 
// FIXME move to PPMA RLV,<regionname>,<settingname>
//list SETTINGS = [
//    "Myriad_Central", "Fine Day",
//    "Myriad_Combat", "Rot",
//    "Myriad_Medieval", "Alchemy Immortalis - Foggy Morning",
//    "Myriad_Modern", "[EUPHORIA] air pollution 2",
//    "Myriad_Future", "Blizzard",
//    "Lani", "Arrakis",
//    "ixi", "Arrakis",
//    //"Bade Plaza", "",
//    "Lbsa Plaza", "Annyka's Soft Lavender Day",
//    //"Recreation Plaza", "",
//    //"Sandbox Plaza", "",
//    //"Sandbox Plaza II", "",
//    "Seaprior Plaza", "Sailor's Delight",
//    //"Teravus Plaza", "",
//    //"Wright Plaza", "",
//    //"Zaius Plaza", "",
//    //"Jump4000", "",
//    //"Jump8000", "",
//    //"Cuteulala Park", "",
//    "OSgrid Welcome Station", "Default"
//];
 
//
// PPMA GET_VAL
//
string KEY_NOT_FOUND = "[KEY_NOT_FOUND]";
string GET_VAL(string dbkey,string field) {
    //OWNERSAY("GET_VAL KEY=["+dbkey+"] FIELD=["+field+"]");
    string out = KEY_NOT_FOUND;
    integer i;
    string name;
    string desc;
    for ( i = 2; i <= llGetNumberOfPrims(); i++ ) {
        name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0);
        desc = llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0);
        if ( llToLower(name) == llToLower(dbkey) && llToLower(desc) == llToLower(field) ) {
            out = llList2String(llGetLinkPrimitiveParams(i,[PRIM_TEXT]),0);
            //DEBUG("GET_VAL RETURN=["+out+"]");
            return out; // bail on first match?
        }
    }
    //OWNERSAY("GET_VAL RETURN=["+out+"]");
    return out;
}
 
SET_VAL(string dbkey, string field, string val) {
    //OWNERSAY("SET_VAL KEY=["+dbkey+"] FIELD=["+field+"] VAL=["+val+"]");
    integer i;
    string name;
    string desc;
    integer written = FALSE;
    for ( i = 2; i <= llGetNumberOfPrims(); i++ ) {
        name = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0),STRING_TRIM);
        desc = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0),STRING_TRIM);
        if ( ( llToLower(name) == llToLower(dbkey) && llToLower(desc) == llToLower(field) ) && written == FALSE ) {
            //OWNERSAY("SET_VAL UPDATE RECORD=["+(string)i+"] DBKEY=["+dbkey+"] DESC=["+field+"] VAL=["+val+"]");
            llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,dbkey,PRIM_DESC,field,PRIM_TEXT,val,ZERO_VECTOR,0.0]);
            written = TRUE; // we did an update, remember it
        }    
    }
    if ( written == TRUE ) {
        //OWNERSAY("SET_VAL UPDATE COMPLETE.");
        return;
    }
    // data hasn't been written, scan for free prim
    for ( i = 2; i <= llGetNumberOfPrims(); i++ ) {
        name = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0),STRING_TRIM);
        desc = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0),STRING_TRIM);
        if ( ( name == "" && desc == "" ) && written == FALSE ) {
            //OWNERSAY("SET_VAL INSERT RECORD=["+(string)i+"] DBKEY=["+dbkey+"] DESC=["+field+"] VAL=["+val+"]");
            llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,dbkey,PRIM_DESC,field,PRIM_TEXT,val,ZERO_VECTOR,0.0]);
            written = TRUE; // we did an update, remember it
        }
    }
    if ( written == TRUE ) {
        //OWNERSAY("SET_VAL INSERT COMPLETED.");
        return;
    }
    //OWNERSAY("SET_VAL NO FREE RECORD FOUND TO INSERT INTO! DATA LOST");
}
 
//////////////////////////////////////////////////////////////////////////////
// FLAG FUNCTIONS
// INCAPACITATED - lost wounds
// DEAD - lost critical wounds
// DEBUG - show debug messages or not
// IDEA: INDECISION - lost resolve?
 
// LMIM: SET_FLAG|<name>=<TRUE|FALSE>
// PPMA: FLAG,<flagname>,<TRUE|FALSE>
// LMOUT: FLAG|<flagname>=<TRUE|FALSE>
// LMERR: FIXME
integer GET_FLAG(string flag) {
    string val = GET_VAL("FLAG",llToUpper(flag));
    if ( val == KEY_NOT_FOUND ) {
        ERROR("Flag ["+flag+"] does not exist.");
    }
    if ( val != "0" && val != "1") {
        ERROR("Flag: "+flag+" invalid value ["+val+"]");
    }
    integer bool = (integer)val;
    return bool;
}
 
// SET_FLAG
// LMIM: SET_FLAG|<flagname>=<TRUE|FALSE>
// PPMA: FLAG,<flagname>,<TRUE|FALSE>
// LMOUT: SET_FLAG|<flagname>=<TRUE|FALSE>
// LMERR: FIXME
SET_FLAG(string flag,integer value) {
    if ( flag == "" ) return; // FIXME add error
    if ( value != TRUE && value != FALSE ) return; // FIXME add err
    SET_VAL("FLAG",llToUpper(flag),(string)value);
}
 
//
// GET_RLVREGION - check PPMA for RLV,<regionname>,<setting>
//
string GET_RLV(string setting) {
    if ( setting == "" ) {
        ERROR("GET_RLV passed empty setting");
        return "";
    }
    string value = GET_VAL("RLV",setting);
    if ( value == KEY_NOT_FOUND ) value = "";
    return value;
}
 
//
// SET_RLV
//
SET_RLV(string setting,string value) {
    if ( setting == "" || value == "" ) {
        ERROR("SET_RLV passed empty setting or value.");
        return;
    }
    SET_RLV(setting,value);
}
 
// DEBUG - show debug chat with wearer name for sorting
DEBUG(string dmessage) {
    if ( GET_FLAG("DEBUG") == TRUE ) llMessageLinked(LINK_THIS,MODULE_RLV,"DEBUG|"+dmessage,llGetOwner());
}
 
// ERROR - show errors on debug channel with wearer name for sorting
ERROR(string emessage) {
    llMessageLinked(LINK_THIS,MODULE_RLV,"ERROR|"+emessage,llGetOwner());
}
 
// MEMORY
GET_MEMORY() {
    OWNERSAY(BASENAME+" free memory: "+(string)llGetFreeMemory()); // show this module's free memory info
}
 
// GETVERSION
GET_VERSION() {
    OWNERSAY(BASENAME+" v"+VERSION+"-"+VERSIONDATE); // show this module's version info
}
 
// HELP
HELP(string help) {
    llMessageLinked(LINK_THIS,MODULE_RLV,"HELP|"+help,llGetOwner());
}
 
OWNERSAY(string str) {
    llMessageLinked(LINK_THIS,MODULE_RLV,"OWNERSAY|"+str,llGetOwner());
}
 
PARSE(string message,key id) {
    DEBUG("PARSE message=["+message+"] id=["+(string)id+"]");
    // Debug handled in say and link events
    // First - handle type 1 messages that do not require breaking down
    list tokens = llParseString2List(message,["|"],[]);
    string cmd = llToLower(llStringTrim(llList2String(tokens,0),STRING_TRIM));
    //string data = llList2String(tokens,1);
    //list subtokens = llParseString2List(data,["="],[]);
    //string attrib = llList2String(subtokens,0);
    //integer idata = llList2Integer(subtokens,1);
    //string sdata = llList2String(subtokens,1);
 
    if ( cmd == "memory" ) { GET_MEMORY(); return; }
    if ( cmd == "reset" ) { RESET(); return;}
    if ( cmd == "version" ) { GET_VERSION(); return;}
 
    // REMOVEME all GET_* command blocks once PPMA is integrated in all HUD scripts    
    if ( cmd == "rlv_ic" ) { RLV_IC(); return;} // switch to IC mode
    if ( cmd == "rlv_ooc" ) { RLV_OOC(); return;} // switch to OOC mode
    if ( cmd == "rlv_version" ) { RLV_VERSION(); return;}
    if ( cmd == "rlv_versionnew" ) { RLV_VERSIONNEW(); return;}
    if ( cmd == "rlv_versionnum" ) { RLV_VERSIONNUM(); return;}
} 
 
//
// RESET
//
RESET() {
    // do anything to clean up before reset
    llResetScript();
}
 
RLV_CLOSE() {
    if (RLV_HAND != 0) llListenRemove(RLV_HAND);
    RLV_CHAN = -1;
    llSetTimerEvent(0.0);
    RLV_CMD = "";
}
 
RLV_IC() {
    // FIXME region tool to enable OOC and in IC - location narrator?
    //if ( RLV_AVAIL == TRUE ) {
        list details = llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_OWNER]);
        key parcelowner = llList2String(details,0);        
        llOwnerSay("@fly=n"); // RPG: Allow/prevent flying @fly=<y/n>
        llOwnerSay("@alwaysrun=n"); // RPG: Allow/prevent always running: @alwaysrun=<y/n>
        llOwnerSay("@redirchat:44=add"); // RPG: Redirect public chat to private channels: @redirchat:<channel>=<rem/add>
        // llOwnerSay("@sendchannel:<channel>=y"); // RPG: Allow/prevent using any chat channel but certain channels : @sendchannel[:<channel>]=<y/n> -- FIXME only allow Myriad channels
        // llOwnerSay("@sendchannel:<channe>=y"); // RPG: Allow/prevent using any chat channel but certain channels, secure way : @sendchannel_sec[:<channel>]=<y/n> -- FIXME only allow Myriad channels
        llOwnerSay("@sendim=n"); // RPG: Allow/prevent sending instant messages : "@sendim=<y/n>" 
        llOwnerSay("@sendim_sec=n"); // RPG: Allow/prevent sending instant messages, secure way : "@sendim_sec=<y/n>" 
        llOwnerSay("@sendimto:"+(string)parcelowner+"=y"); // RPG: Allow/prevent sending instant messages to someone in particular : "@sendimto:<UUID>=<y/n>" -- FIXME allow to region owner/staff
        llOwnerSay("@startimto:"+(string)parcelowner+"=y"); // RPG: Allow/prevent starting an IM session with someone in particular : "@startimto:<UUID>=<y/n>" -- FIXME allow to region owner/staff
        llOwnerSay("@recvim=n"); // RPG: Allow/prevent receiving instant messages : "@recvim=<y/n>" 
        llOwnerSay("@recvim_sec=n"); // RPG: Allow/prevent receiving instant messages, secure way : "@recvim_sec=<y/n>"
        llOwnerSay("@recvimfrom:"+(string)parcelowner+"=y"); // RPG: Allow/prevent receiving instant messages from someone in particular : "@recvimfrom:<UUID>=<y/n>"  - FIXME allow from region owner/staff
        llOwnerSay("@tplm=n"); // RPG: Allow/prevent teleporting to a landmark : "@tplm=<y/n>" 
        llOwnerSay("@tploc=n"); // RPG: Allow/prevent teleporting to a location : "@tploc=<y/n>"
        llOwnerSay("@tplure=n"); // RPG: Allow/prevent teleporting by a friend : "@tplure=<y/n>"
        llOwnerSay("@tplure_sec=n"); // RPG: Allow/prevent teleporting by a friend, secure way : "@tplure_sec=<y/n>" 
        llOwnerSay("@sittp=n"); // RPG: Unlimit/limit sit-tp : "@sittp=<y/n>" 
        llOwnerSay("@standtp=n"); // RPG: Allow/prevent standing up at a different location than where we sat down : @standtp=<y/n> 
        llOwnerSay("@accepttp:"+(string)parcelowner+"=add"); // RPG: Remove/add auto-accept teleport offers from a particular avatar : "@accepttp[:<UUID>]=<rem/add>" -- FIXME allow from region owner/staff
        llOwnerSay("@showinv=n"); // RPG: Allow/prevent using inventory : @showinv=<y/n>
        llOwnerSay("@viewnote=n"); // RPG: Allow/prevent reading notecards : @viewnote=<y/n>
        llOwnerSay("@viewscript=n"); // RPG: Allow/prevent opening scripts : @viewscript=<y/n> 
        llOwnerSay("@viewtexture=n"); // RPG: Allow/prevent opening textures : @viewtexture=<y/n> 
        llOwnerSay("@edit=n"); // RPG: Allow/prevent editing objects : "@edit=<y/n>" 
        llOwnerSay("@rez=n"); // RPG: Allow/prevent rezzing inventory : "@rez=<y/n>" -- FIXME TEST IF THIS AFFECTS BULLETS
        llOwnerSay("@fartouch=n"); // RPG: Allow/prevent touching objects located further than 1.5 meters away from the avatar : @fartouch=<y/n> 
        llOwnerSay("@showworldmap=n"); // RPG: Allow/prevent viewing the world map : @showworldmap=<y/n>  -- FIXME only allow when holding MAP item
        llOwnerSay("@showminimap=n"); // RPG: Allow/prevent viewing the mini map : @showminimap=<y/n> -- FIXME only allow when holding SCANNER item
        llOwnerSay("@showloc=n"); // RPG: Allow/prevent knowing the current location : @showloc=<y/n>
        llOwnerSay("@shownames=n"); // RPG: Allow/prevent seeing the names of the people around : @shownames=<y/n> 
        llOwnerSay("@showhovertextall=n"); // RPG: Allow/prevent seeing all the hovertexts : @showhovertextall=<y/n> 
        llOwnerSay("@showhovertext:"+(string)parcelowner+"=y"); // RPG: Allow/prevent seeing one hovertext in particular : @showhovertext:<UUID>=<y/n>  -- FIXME allow see region owner/staff
        llOwnerSay("@showhovertexthud=n"); // RPG: Allow/prevent seeing the hovertexts on the HUD of the user : @showhovertexthud=<y/n> -- FIXME work around for BAM status?
        llOwnerSay("@showhovertextworld=n"); // RPG: Allow/prevent seeing the hovertexts in-world : @showhovertextworld=<y/n> 
        llOwnerSay("@setgroup:Myriad RPG=force"); // RPG: Force the agent to change the active group : @setgroup:<group_name>=force // FIXME get current group - switch to whatever parcel group is
        llOwnerSay("@setgroup=n"); // RPG: Allow/prevent activating a group : @setgroup=<y/n>
        llOwnerSay("@setenv=n"); // RPG: Allow/prevent changing the environment settings : @setenv=<y/n> 
        // llOwnerSay("@setenv_preset:<presetname> =force"); // RPG: Force change an environment setting : @setenv_<setting>:<value>=force (*) -- FIXME set world, drug, incapacitated, dead, magic  effects
 
        OWNERSAY("Myriad Lite RLV IC Mode enabled");
    //}
}
 
RLV_OOC() {
    // FIXME region tool to enable OOC and in IC - location narrator?
    //if ( RLV_AVAIL == TRUE ) {
        list details = llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_OWNER]);
        key parcelowner = llList2String(details,0);        
        llOwnerSay("@fly=y"); // RPG: Allow/prevent flying @fly=<y/n>
        llOwnerSay("@alwaysrun=y"); // RPG: Allow/prevent always running: @alwaysrun=<y/n>
        llOwnerSay("@redirchat:44=rem"); // RPG: Redirect public chat to private channels: @redirchat:<channel>=<rem/add>
        // llOwnerSay("@sendchannel:<channel>=y"); // RPG: Allow/prevent using any chat channel but certain channels : @sendchannel[:<channel>]=<y/n> -- FIXME only allow Myriad channels
        // llOwnerSay("@sendchannel:<channe>=y"); // RPG: Allow/prevent using any chat channel but certain channels, secure way : @sendchannel_sec[:<channel>]=<y/n> -- FIXME only allow Myriad channels
        llOwnerSay("@sendim=y"); // RPG: Allow/prevent sending instant messages : "@sendim=<y/n>" 
        llOwnerSay("@sendim_sec=y"); // RPG: Allow/prevent sending instant messages, secure way : "@sendim_sec=<y/n>" 
        //llOwnerSay("@sendimto:"+(string)parcelowner+"=y"); // RPG: Allow/prevent sending instant messages to someone in particular : "@sendimto:<UUID>=<y/n>" -- FIXME allow to region owner/staff
        //llOwnerSay("@startimto:"+(string)parcelowner+"=y"); // RPG: Allow/prevent starting an IM session with someone in particular : "@startimto:<UUID>=<y/n>" -- FIXME allow to region owner/staff
        llOwnerSay("@recvim=y"); // RPG: Allow/prevent receiving instant messages : "@recvim=<y/n>" 
        llOwnerSay("@recvim_sec=y"); // RPG: Allow/prevent receiving instant messages, secure way : "@recvim_sec=<y/n>"
        //llOwnerSay("@recvimfrom:"+(string)parcelowner+"=y"); // RPG: Allow/prevent receiving instant messages from someone in particular : "@recvimfrom:<UUID>=<y/n>"  - FIXME allow from region owner/staff
        llOwnerSay("@tplm=y"); // RPG: Allow/prevent teleporting to a landmark : "@tplm=<y/n>" 
        llOwnerSay("@tploc=y"); // RPG: Allow/prevent teleporting to a location : "@tploc=<y/n>"
        llOwnerSay("@tplure=y"); // RPG: Allow/prevent teleporting by a friend : "@tplure=<y/n>"
        llOwnerSay("@tplure_sec=y"); // RPG: Allow/prevent teleporting by a friend, secure way : "@tplure_sec=<y/n>" 
        llOwnerSay("@sittp=y"); // RPG: Unlimit/limit sit-tp : "@sittp=<y/n>" 
        llOwnerSay("@standtp=y"); // RPG: Allow/prevent standing up at a different location than where we sat down : @standtp=<y/n> 
        llOwnerSay("@accepttp:"+(string)parcelowner+"=rem"); // RPG: Remove/add auto-accept teleport offers from a particular avatar : "@accepttp[:<UUID>]=<rem/add>" -- FIXME allow from region owner/staff
        llOwnerSay("@showinv=y"); // RPG: Allow/prevent using inventory : @showinv=<y/n>
        llOwnerSay("@viewnote=y"); // RPG: Allow/prevent reading notecards : @viewnote=<y/n>
        llOwnerSay("@viewscript=y"); // RPG: Allow/prevent opening scripts : @viewscript=<y/n> 
        llOwnerSay("@viewtexture=y"); // RPG: Allow/prevent opening textures : @viewtexture=<y/n> 
        llOwnerSay("@edit=y"); // RPG: Allow/prevent editing objects : "@edit=<y/n>" 
        llOwnerSay("@rez=y"); // RPG: Allow/prevent rezzing inventory : "@rez=<y/n>" -- FIXME TEST IF THIS AFFECTS BULLETS
        llOwnerSay("@fartouch=y"); // RPG: Allow/prevent touching objects located further than 1.5 meters away from the avatar : @fartouch=<y/n> 
        llOwnerSay("@showworldmap=y"); // RPG: Allow/prevent viewing the world map : @showworldmap=<y/n>  -- FIXME only allow when holding MAP item
        llOwnerSay("@showminimap=y"); // RPG: Allow/prevent viewing the mini map : @showminimap=<y/n> -- FIXME only allow when holding SCANNER item
        llOwnerSay("@showloc=y"); // RPG: Allow/prevent knowing the current location : @showloc=<y/n>
        llOwnerSay("@shownames=y"); // RPG: Allow/prevent seeing the names of the people around : @shownames=<y/n> 
        llOwnerSay("@showhovertextall=y"); // RPG: Allow/prevent seeing all the hovertexts : @showhovertextall=<y/n> 
        // llOwnerSay("@showhovertext:"+(string)parcelowner+"=y"); // RPG: Allow/prevent seeing one hovertext in particular : @showhovertext:<UUID>=<y/n>  -- FIXME allow see region owner/staff
        llOwnerSay("@showhovertexthud=y"); // RPG: Allow/prevent seeing the hovertexts on the HUD of the user : @showhovertexthud=<y/n> -- FIXME work around for BAM status?
        llOwnerSay("@showhovertextworld=y"); // RPG: Allow/prevent seeing the hovertexts in-world : @showhovertextworld=<y/n> 
        //llOwnerSay("@setgroup:Myriad RPG=force"); // RPG: Force the agent to change the active group : @setgroup:<group_name>=force 
        llOwnerSay("@setgroup=y"); // RPG: Allow/prevent activating a group : @setgroup=<y/n>
        llOwnerSay("@setenv=y"); // RPG: Allow/prevent changing the environment settings : @setenv=<y/n> 
        // llOwnerSay("@setenv_preset:<presetname> =force"); // RPG: Force change an environment setting : @setenv_<setting>:<value>=force (*) -- FIXME set world, drug, incapacitated, dead, magic  effects
 
        OWNERSAY("Myriad Lite RLV OOC Mode enabled");
    //}
}
 
RLV_OPEN() {
    RLV_CLOSE();
    RLV_HAND = llListen(RLV_CHAN,"",NULL_KEY,"");
    llSetTimerEvent(60.0);
}
 
//////////////////////////////////////////////////////////////////////////////
// RLV TPTO FORCE TELEPORT EXAMPLE
// Listens on channel 4 for local coordinates and a sim name
// and tells your viewer to teleport you there.
//
// By Marine Kelley 2008-08-26
// RLV version required : 1.12 and above
//
// HOW TO USE :
//   * Create a script inside a box
//   * Overwrite the contents of the script with this one
//   * Wear the box
//   * Say the destination coords Region/X/Y/Z on channel 4 :
//     Example : /4 Help Island Public/128/128/50
 
//key kRequestHandle; // UUID of the dataserver request
//vector vLocalPos;   // local position extracted from the
 
//Init () {
//  kRequestHandle = NULL_KEY;
//  llListen (4, "", llGetOwner (), "");
//}
 
//default {
//  state_entry () {
//    Init ();
//  }
 
//  on_rez(integer start_param) {
//    Init ();
//  }
 
//  listen(integer channel, string name, key id, string message) {
//    list tokens = llParseString2List (message, ["/"], []);
//    integer L = llGetListLength (tokens);
 
//    if (L==4) {
//      // Extract local X, Y and Z
//      vLocalPos.x = llList2Float (tokens, 1);
//      vLocalPos.y = llList2Float (tokens, 2);
//      vLocalPos.z = llList2Float (tokens, 3);
 
      // Request info about the sim
//      kRequestHandle=llRequestSimulatorData (llList2String (tokens, 0), DATA_SIM_POS);
//    }
//  }
 
//  dataserver(key queryid, string data) {
//    if (queryid == kRequestHandle) {
      // Parse the dataserver response (it is a vector cast to a string)
//      list tokens = llParseString2List (data, ["<", ",", ">"], []);
//      string pos_str = "";
//      vector global_pos;
 
      // The coordinates given by the dataserver are the ones of the
      // South-West corner of this sim
      // => offset with the specified local coordinates
//      global_pos.x = llList2Float (tokens, 0);
//      global_pos.y = llList2Float (tokens, 1);
//      global_pos.z = llList2Float (tokens, 2);
//      global_pos += vLocalPos;
 
      // Build the command
//      pos_str =      (string)((integer)global_pos.x)
//                +"/"+(string)((integer)global_pos.y)
//                +"/"+(string)((integer)global_pos.z);
//      llOwnerSay ("Global position : "+(string)pos_str); // Debug purposes
 
      // Fire !
//      llOwnerSay ("@tpto:"+pos_str+"=force");
//    }
//  }
//}
//////////////////////////////////////////////////////////////////////////////
 
RLV_VERSION() {
    RLV_OPEN();
    llOwnerSay("@version="+(string)RLV_CHAN);
}
 
RLV_VERSIONNEW() {
    RLV_OPEN();
    llOwnerSay("@versionnew="+(string)RLV_CHAN);
}
 
RLV_VERSIONNUM() {
    RLV_CMD="versionnum";
    RLV_OPEN();
    llOwnerSay("@versionnum="+(string)RLV_CHAN);
}
 
// RPEVENT
RPEVENT(string rpevent) {
    llMessageLinked(LINK_THIS,MODULE_RLV,"RPEVENT|"+rpevent,llGetOwner());
}
 
SETUP() {
    RLV_VERSIONNEW();    
    RLV_OOC();
    OWNERSAY("RLV module active.");
}
 
SETUP_WINDLIGHT() {
    if ( RLV_AVAIL == TRUE ) {
        // check altitude
        CURPOS = llGetPos();
        GROUND_LEVEL = llFloor(llGround(<0,0,0>));
        if ( CURPOS.z >= ( GROUND_LEVEL + SPACE_OFFSET ) ) {
            OWNERSAY("RestrainedLight configuring Midnight for Space.");
            llOwnerSay("@setenv_preset:midnight=force");
        } else {
            string setting = GET_RLV("RL_"+llGetRegionName());
            if ( setting != "" ) {
                llOwnerSay("@setenv_preset:"+setting+"=force");
                OWNERSAY("RestrainedLight set to "+setting+" for region "+llGetRegionName());
            } else {
                llOwnerSay("@setenv_preset:Default=force");
                OWNERSAY("RestrainedLight set to Default for region "+llGetRegionName());
            }
        }
    } else {
        OWNERSAY("Please enabled RestrainedLove Viewer features to activate RestrainedLight.");
    }
}
 
 
default {
 
    changed(integer changes) {
        if ( ( RLV_AVAIL == TRUE ) && ( ( changes & CHANGED_REGION ) || (changes & CHANGED_TELEPORT ) ) ) {
            SETUP_WINDLIGHT();
        }
    }  
 
    link_message(integer sender_num,integer num,string str,key id) {
        if ( num == MODULE_RLV || num == LM_SENDTOATTACHMENT ) return; // ignore our own messages
        list tokens = llParseString2List(str,["|"],[]);
        string cmd = llToLower(llStringTrim(llList2String(tokens,0),STRING_TRIM));
 
        if ( cmd == "debug" || cmd == "error" || cmd == "help" || cmd == "ownersay" || cmd == "rpevent" ) return; // ignore WELL commands
        // show debug only when not ignoring other commands
        DEBUG("EVENT: link_message("+(string)sender_num+","+(string)num+","+str+","+(string)id+")");             
        PARSE(str,id);
    }
 
    listen(integer channel,string name,key id,string message) {
        DEBUG("EVENT listen channel=["+(string)channel+"] name=["+name+"] id=["+(string)id+"] message=["+message+"]");
        if ( channel != RLV_CHAN ) return; // woken up for message that is not for this module FIXME show error?
        if ( RLV_CMD == "versionnum" ) {
            if ( (integer)message > 2080000 ) {
                RLV_AVAIL = TRUE;
            }
            RLV_CLOSE();
            return;
        }
    }
 
    state_entry() {
        SETUP();
    }
 
    timer() {
        RLV_CLOSE();
    }
}
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
DokuWiki