Greeter

From Second Life Wiki
Jump to: navigation, search
KBnote.png Note: Due to licensing issues, all contributions to this wiki have stopped and the articles that we posted are just being maintained. This is one of the projects that has gone further and for updates you are cordially invited to the project page on our wiki.

About

This is a standard visitor greeter, compatible with the subscriber mail system I wrote, which allows:

  • Sending an instant message whenever a new visitor is detected.
  • Handing out a landmark, a notecard and a gift.
  • Letting visitors subscribe (compatible with the subscriber mail system).
  • Sending an URL.
  • Keeping statistics of visitors and the number of requested items from the greeter.
  • Access list for shared management of the greeter.

Setup

In order to make this greeter work, you would have to place it somewhere close to the landing point so that new visitors get scanned more efficiently. To set it up, first create a notecard called Access containing the avatar names of administrators line-by-line. For example, if avatar "Kira Komarov" and avatar "Lance Lenoirre" should both be able to manage the greeter, the notecard would look like this:

Kira Komarov
Lance Lenoirre

You can add as many administrators as you like to the notecard. Next, configure the script so that it matches your liking. The section in the script that you should change is the one marked with the "CONFIGURATION" comment:

///////////////////// CONFIGURATION //////////////////
string GREET_MESSAGE = "Hello!";
string DIALOG_MESSAGE = "Welcome, please select from the options below: ";
string SUBSCRIBE_MESSAGE = "Thank you for subscribing! We will keep you updated!";
integer SCAN_RANGE = 10;
integer SCAN_INTERVAL = 2;
string URL = "http://wiki.secondlife.com/wiki/Greeter";
list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Notecard", "Gift"];
key INVITE_GROUP_KEY = "9092e77a-ed89-508d-30a9-456873423901";
string INVITE_GROUP_MESSAGE = "To join the group, please click the link in your history window (ctrl+h):";
/////////////////////////////////////////////////////
  • The GREET_MESSAGE is the message that your visitors will get once they are scanned. You can change it from the factory default "Hello!" to anything else. For example, you could change it to:
string GREET_MESSAGE = "Hello and welcome to The Chocolate Factory! Please enjoy our cocoa...";
  • The DIALOG_MESSAGE is what the visitors will see in the dialog description, which will pop up on their screen. Usually this is used to describe the options on the buttons, however, just like the GREET_MESSAGE you may change to anything that suits you.
  • The SUBSCRIBE_MESSAGE is the message that the greeter will send after a visitor has subscribed. You can change this of course to your liking.
  • The SCAN_RANGE is the range in meters that the greeter will scan for new visitors. The factory default is 10 meters and it can go up to 96 meters. To change this, for example to make the scanning range 30 meters, one would modify the line like this:
string SCAN_RANGE = 30;
  • The SCAN_INTERVAL, similar to the SCAN_RANGE is the frequency with which the greeter will scan for new visitors. The factory default is to scan every two seconds and you can change this as you like.
  • The URL is an optional URL or message that can be sent to a visitor once they press the "URL" button. The factor default is just a link to this article.
  • The USER_OPTIONS is the main feature control of the greeter. It is a list consisting of options provided to the visitors when they get scanned by the greeter. By modifying this line, you can change what the greeter will provide to the visitors. For example, the factory default has all the options turned on:
list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Notecard", "Group", "Gift"];

This means that the greeter will offer landmarks, offer subscriptions, offer to send URLs, offer to send a notecard and offer to send a gift. However, you might not want to send gifts, for example. In that case, you can disable the gift sending feature by simply modifying this line. For example, to disable the gift sending option, you would change this line to:

list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Notecard", "Group" ];
  • The INVITE_GROUP_KEY is the key to a group you would want the greeter to invite you to.
  • The INVITE_GROUP_MESSAGE is the message that will be sent to the user before they are invited to the group. It also contains the group link they will have to click in order to get the group information and be able to join.

The final step is to add a landmark, a notecard and perhaps a gift to the prim containing the greeter. When a visitor clicks an option, say "Landmark", the greeter will hand out the first landmark in the prim. The same applies, to notecards and gifts (objects). The greeter does not support sending multiple objects, however you can always bundle a bunch of stuff in an object and send it as a gift.

To connect the greeter with the subscriber mail system, an administrator on the access list would have to select "Dump Subs". This will make the greeter list all subscribers line by line in the subscriber mailing system's Subscriber notecard format. For example, from time to time after users have subscribed using the greeter, an administrator would have to click the greeter and select "Dump Subs", this will subscribers line-by-line:

1ad33407-a792-476d-a5e3-06007c0802bf#Kira Komarov
82c73d6d-facf-4332-b17b-06d8cd66a116#Lance Lenoirre

The administrator will copy these lines and paste them into the subscriber mail system Subscriber notecard in order to make the subscriber mail system work.

Hacks

  • One hack you can do is to change the buttons. For example, instead of "Notecard" you would want to have something like "Rules". In order to make this example change, you have to modify:
list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Notecard", "Gift", "Group"];

to:

list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Rules", "Gift", "Group"];

AS WELL as change the line:

if(message == "Notecard") {

to:

if(message == "Rules") {

and proceed the same with every button you wish to change.

Code

//////////////////////////////////////////////////////////
// [K] Kira Komarov - 2011, License: GPLv3              //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
///////////////////// CONFIGURATION //////////////////
string GREET_MESSAGE = "Hello!";
string DIALOG_MESSAGE = "Welcome, please select from the options below: ";
string SUBSCRIBE_MESSAGE = "Thank you for subscribing! We will keep you updated!";
integer SCAN_RANGE = 10;
integer SCAN_INTERVAL = 2;
string URL = "http://wiki.secondlife.com/wiki/Greeter";
list USER_OPTIONS = ["Landmark", "Subscribe", "URL", "Notecard", "Gift", "Group"];
key INVITE_GROUP_KEY = "9092e87a-ed89-509d-30a9-456873423901";
string INVITE_GROUP_MESSAGE = "To join the group, please click the link in your history window (ctrl+h):";
/////////////////////////////////////////////////////
 
///////////////////// INTERNALS /////////////////////
list aList = [];
key aQuery = NULL_KEY;
list nList = [];
list kList = [];
list sList = [];
integer aLine = 0;
integer comChannel;
integer comHandle;
 
integer sLandmark = 0;
integer sGift = 0;
integer sNotecard = 0;
integer sURL = 0;
 
default
{
    state_entry()
    {
        integer itra;
        for(itra=0; itra<llGetInventoryNumber(INVENTORY_NOTECARD); ++itra) {
            if(llGetInventoryName(INVENTORY_NOTECARD, itra) == "Access")
                jump found_access;
        }
        return;
@found_access;
        aLine = 0;
        aList = [];
        aQuery = llGetNotecardLine("Access", aLine);
        comChannel = ((integer)("0x"+llGetSubString((string)llGetKey(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
        comHandle = llListen(comChannel, "", "", "");
        llSensorRepeat("",NULL_KEY,1,SCAN_RANGE,PI,SCAN_INTERVAL);
    }
 
    touch_start(integer total_number)
    {
        if(~llListFindList(aList, (list)llDetectedName(0)))
            jump admin;
        llDialog(llDetectedKey(0), DIALOG_MESSAGE, USER_OPTIONS, comChannel);
        return;
@admin;
        llDialog(llDetectedKey(0), "Welcome to the greeter control, please choose your configuration options: \n", [ "Visitors", "Dump Subs", "Statistics" ], comChannel);
    }
 
    listen(integer channel, string name, key id, string message) {
 
        if(message == "Group") {
            llInstantMessage(id, INVITE_GROUP_MESSAGE + "\n secondlife:///app/group/" + (string)INVITE_GROUP_KEY + "/about");
            jump user_remenu;
        }
 
        if(message == "Landmark") {
            if(llGetInventoryNumber(INVENTORY_LANDMARK) == 0) {
                llInstantMessage(id, "Sorry, no landmark is available at this time.");
                jump user_remenu;
            }
            llGiveInventory(id, llGetInventoryName(INVENTORY_LANDMARK, 0));
            ++sLandmark;
            jump user_remenu;
        }
 
        if(message == "Gift") {
            if(llGetInventoryNumber(INVENTORY_OBJECT) == 0) {
                llInstantMessage(id, "Sorry, no gift is available at this time.");
                jump user_remenu;
            }
            llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0));
            ++sGift;
            jump user_remenu;
        }
 
        if(message == "Notecard") {
            integer itra;
            string card;
            for(itra=0; itra<llGetInventoryNumber(INVENTORY_NOTECARD); ++itra) {
                if(llGetInventoryName(INVENTORY_NOTECARD, itra) != "Access") {
                    card = llGetInventoryName(INVENTORY_NOTECARD, itra);
                    jump found_card;
                }
            }
            llInstantMessage(id, "Sorry, no notecard is available at this time.");
            jump user_remenu;
@found_card;
            llGiveInventory(id, card);
            ++sNotecard;
            jump user_remenu;
        }
 
        if(message == "URL") {
            llInstantMessage(id, URL);
            ++sURL;
            jump user_remenu;
        }
 
        if(message == "Subscribe") {
            sList += (list)id + (list)name;
            llInstantMessage(id, SUBSCRIBE_MESSAGE);
            jump user_remenu;
        }
 
        if(!~llListFindList(aList, (list)name))
            return;
 
        if(message == "Visitors") {
            integer itra;
            llInstantMessage(id, "----------------------- Visitors -------------------------");
            for(itra=0; itra<llGetListLength(nList); itra+=3) {
                llInstantMessage(id, llList2String(nList, itra) + " / " + llList2String(nList, itra+1) + " @ " + llList2String(nList, itra+2));
                llInstantMessage(id, "------------------------------------------------------------");
            }
            return;
        }
 
        if(message == "Dump Subs") {
            integer itra;
            for(itra=0; itra<llGetListLength(sList); itra+=2) {
                llInstantMessage(id, llList2String(sList, itra) + "#" + llList2String(sList, itra+1));
            }
            return;
        }
 
        if(message == "Statistics") {
            llInstantMessage(id, "---------------------- Statistics ------------------------");
            llInstantMessage(id, "Total number of unique visitors: " + (string)(llGetListLength(nList)/3));
            llInstantMessage(id, "Total number of subscribers: " + (string)(llGetListLength(sList)/2));
            llInstantMessage(id, "Total number of landmarks handed out: " + (string)sLandmark);
            llInstantMessage(id, "Total number of gifts handed out: " + (string)sGift);
            llInstantMessage(id, "Total number of notecards handed out: " + (string)sNotecard);
            llInstantMessage(id, "Total number of URLs requested: " + (string)sURL);
            llInstantMessage(id, "------------------------------------------------------------");
            return;
        }
 
        return;
@user_remenu;
        llDialog(id, DIALOG_MESSAGE, USER_OPTIONS, channel);
        return;       
    }
 
    sensor(integer num_detected) {
        integer itra;
        for(itra=num_detected-1; itra>-1; --itra) {
            if(!~llListFindList(nList, (list)llDetectedName(itra))) {
                nList += (list)llDetectedName(itra) + (list)llGetDisplayName(llDetectedKey(itra)) + (list)llGetTimestamp();
                kList += (list)llDetectedKey(itra);
                llInstantMessage(llDetectedKey(itra), GREET_MESSAGE);
                llDialog(llDetectedKey(itra), DIALOG_MESSAGE, USER_OPTIONS, comChannel);
            }
        }
    }
 
    dataserver(key query_id, string data) {
        if(query_id == aQuery) {
            if(data == EOF) return;
            if(data == "") jump next_access;
            aList += (list) data;
@next_access;
            ++aLine;
            aQuery = llGetNotecardLine("Access", aLine);
        }
    }
}

If you have any questions, or need help setting this system up, feel free to contact Kira Komarov in-world.