User:Daemonika Nightfire/Scripts/Greeter&Co

From Second Life Wiki
Jump to: navigation, search

*DS* Greeter (volume_detect) v1.0.05

Dieses einfache script ist dafuer gedacht in einem unsichtbaren Object im Eingang oder Teleport Punkt eines Shops zu liegen. Das Object sollte natuerlich gross genug sein, um sicher zu gehen das Besucher auch wirklich durch gehen. Es begruesst jeden Besucher nur 1x am Tag und gibt dir am Ende eines Tages eine Zusammenfassung per InstantMessage.

/*
    *DS* Greeter (volume-detect) ist ein ganz einfacher Besucherzaehler mit Begruessungs-Funktion.
    Damit der Greeter nicht nervt, speichert der jeden neuen AvatarKey in eine Liste um sie am selben Tag nicht erneut zu begruessen.
    Der Greeter zaehlt dabei jeden Avatar und gibt die Anzahl am naechsten Morgen per Instant Message zurueck.
    (Wenn du Email-Weiterleitung aktiviert hast, bekommst du die Instant Message an deine Email-Adresse geschickt.)
 
    Zudem verfuegt der Greeter ueber eine Speicherkontrolle, um eine Speicher-Ueberladung (Stack Heap Collision) zu vermeiden.
 
    Das Script ist ausschliesslich darauf ausgelegt die Anzahl Besucher zu zaehlen und speichert die Keys ledglich temporaer.
    Die Keys werden nicht weiter verarbeitet, entschluesselt oder wiedergegeben.
*/
 
key owner;              // Speicher fuer den OwnerKey
string date;            // Speicher fuer das Datum
vector pos;             // Speicher fuer die Object-Position
string region;          // Speicher fuer den Region-Namen
list parcel;            // Speicher fuer den Parzellen-Namen
 
list visitor_list = []; // Speicher fuer die Besucher-Liste (AvatarKeys)
integer length = 0;     // Speicher fuer die aktuelle Listen-Laenge
integer backup = 0;     // Speicher fuer das backup
 
default
{
    state_entry()
    {
        owner = llGetOwner();                                       // speichert den aktuellen OwnerKey
        date = llGetDate();                                         // speichert das aktuelle Datum
        pos = llGetPos();                                           // speichert die Position
        region = llGetRegionName();                                 // speichert den Region-Namen
        parcel = llGetParcelDetails(pos, [PARCEL_DETAILS_NAME]);    // speichert den Parzellen-Namen
 
        llVolumeDetect(TRUE);   // damit erkennt das Object collision wenn es phantom ist
        llSetTimerEvent(300);   // 5 minuten reicht voellig, schneller waere hirnrissig
    }
 
    collision_start(integer num_detected)
    {
        key Avatar = llDetectedKey(0); // lokale variable fuer den aktuellen AvatarKey
 
        if(Avatar != owner) // wird ausgefuehrt, wenn fremde Avatare collidieren
        {
            if(llGetDisplayName(Avatar)) // damit geht der greeter nicht bei physischen prims los
            {
                if(!~llListFindList(visitor_list, [Avatar])) // prueft ob der aktuelle AvatarKey schon bekannt ist
                {
                    visitor_list += Avatar; // fuegt den unbekannten Avatarkey in der Liste hinzu
                    length = llGetListLength(visitor_list); // zaehlt die anzahl der Eintraege in der Liste
 
                    // ↓↓↓↓↓↓↓↓↓ Bereich fuer individuelle Meldungen, Sounds, Particle usw. ↓↓↓↓↓↓↓↓↓ \\
 
                    llPlaySound("bc8c684d-d3a8-448b-91ae-0286255e6cea", 1.0); // Boing
                    llRegionSayTo(Avatar, 0, "Hello " + llGetDisplayName(Avatar) + ", welcome to " + llList2String(parcel,0));
 
                    // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ \\
 
                    if(llGetFreeMemory() < 10000) // prueft nach jedem AvatarKey ob noch genuegend Memory frei ist
                    {
                        llInstantMessage(owner, "/me Low Memory: cleaning List\nVisitors today: " + (string)length);
 
                        backup += length;   // speichert die aktuelle Anzahl ins backup
                        length = 0;         // setzt den counter auf null
                        visitor_list = [];  // leert die aktuelle Besucher-Liste
                    }
                }
            }
        }
        else if(Avatar == owner) // wird nur ausgefuehrt, wenn der Owner collidiert
        {
            llRegionSayTo(owner, 0, "Welcome back " + llGetDisplayName(owner) + ", you had " + (string)length + " Visitors today.");
        }
    }
 
    timer()
    {
        if(llGetDate() != date) // vergleicht das gespeicherte Datum mit dem aktuellen
        {
            length += backup;   // zaehlt die aktuelle liste mit dem aktuellen backup zusammen
            llInstantMessage(owner, "Visitors yesterday: " + (string)length +
                                    "\nsecondlife:///app/teleport/" + llEscapeURL(region) +
                                                                "/" + (string)(llRound(pos.x)) +
                                                                "/" + (string)(llRound(pos.y)) +
                                                                "/" + (string)(llCeil(pos.z)));
 
            length = 0;         // setzt den counter auf null
            backup = 0;         // setzt das backup auf null
            visitor_list = [];  // leert die aktuelle Besucher-Liste
 
            date = llGetDate(); // aktuallisiert das Datum
        }
    }
 
    on_rez(integer Dae)
    {
        llResetScript(); // resettet das Script beim rezzen
    }  
}

*DS* Visitor Greeter

Dieser Greeter funktioniert Parzellen-/Region-weit und besteht aus 2 Scripten, *DS* Receptor Core v2.0.05 und *DS* Receptor Save v2.0.05. Lege beide Scripte zusammen in den Root eines Objects.

Die Statistik die dieser Greeter erzeugt finde ich wesentlich aufschlussreicher als die Traffik-Anzeige.
In der Traffik-Anzeige kann man naelich nicht erkennen, ob 3000 Traffik von einem Avatar in 10 Stunden,
oder von 10 Avataren in einer Stunde erzeugt wurden.

Fuer einen Shop, Club oder aehnlichem ist die reine Anzahl tatsaechlicher Besucher interessanter.

*DS* Receptor Core v2.0.05

/*
    *DS* Receptor Core v2.0.05
    Hier handelt es sich um das Main-Script eines Region-/Parzell-weiten Greeters.
    Dieses Script fragt lediglich die Keys ab und sendet diese an das Speicher-Script.
    Zudem ist hier die Menue-Verwaltung enthalten.
*/
 
key owner;
string date;
list parcel;
 
float repeat = 5.0; // intervall in sekunden
integer scope = AGENT_LIST_PARCEL;
string s_info = "Parcel";
 
list ON_OFF = ["Online","Offline","Greeter","Silent","Parcel","Region"];
integer status = FALSE;
integer greeting = FALSE;
integer scanner = TRUE;
 
integer unixtime;
integer menu_open = FALSE;
integer menu_handler;
integer menu_channel;
Dialog()
{
    llListenRemove(menu_handler);
    menu_channel = (integer)(llFrand(9999999.0) * -1);
    menu_handler = llListen(menu_channel,"","","");
 
    menu_open = TRUE;
    if(!status)
    {
        llSetTimerEvent(repeat);
    }
 
    string TEXT = "\nStatus 'Offline' (" + s_info + ")";
    if(status)
    {
        TEXT = "\nStatus 'Online' (" + s_info + ")\nupdate every " + (string)repeat + " seconds.";
    }
    llDialog(owner,TEXT,[llList2String(ON_OFF,status),"Reset","Close",llList2String(ON_OFF,scanner+4),llList2String(ON_OFF,greeting+2)], menu_channel);
    unixtime = llGetUnixTime();
}
 
RemoveListener()
{
    if(!status)
    {
        llSetTimerEvent(0);
    }
    menu_open = FALSE;
    llListenRemove(menu_handler);
}
 
default
{
    state_entry()
    {
        owner = llGetOwner();
        date = llGetDate();
        parcel = llGetParcelDetails(llGetPos(), [PARCEL_DETAILS_NAME]);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"- Visitors -\nOFFLINE", <1,0,0>, 1.0]);
    }
 
    timer()
    {
        if(status)
        {
            list Agents = llGetAgentList(scope, []);                        // fragt alle verfuegbaren AvatarKeys in der Region ab
            integer Length = llGetListLength(Agents);                       // gibt an wie viele Eintraege vorhanden sind
            llMessageLinked(LINK_SET, 1000, "COUNT " + (string)Length, ""); // sendet die Anzahl an das Speicher-Script
 
            // ↓ Diese Funktion sendet jeden Key einzeln an das Speicher-Script
            integer index;
            while(index < Length)
            {
                key id = llList2Key(Agents, index);
                llMessageLinked(LINK_SET, 1000, "KEYS " + (string)id, "");
                ++index;
            }
 
            // ↓ Diese Funktion vergleicht das aktuelle Datum und resettet das Speicher-Script
            if(llGetDate() != date)
            {
                llMessageLinked(LINK_SET, 1000, "RESET", "");
                date = llGetDate(); // hier wird das Datum aktuallisiert
            }
        }
 
        if(menu_open && (llGetUnixTime() - unixtime) > 30)
        {
            RemoveListener();
        }
    }
 
    touch_start(integer total_number)
    {
        if(llDetectedKey(0) == owner)
        {
            Dialog(); // oeffnet das Menue
        }
    }
 
    link_message(integer sender_num, integer num, string msg, key id) 
    {
        if(num == 2000) // empfaengt den Key vom Speicher-Script und sendet eine Begruessung an diesen Key
        {
            if(greeting) // Natuerlich nur wenn die Greeter Funktion eingeschaltet ist
            {
                llRegionSayTo(msg, 0, "Hello " + llGetDisplayName(msg) + ", welcome to " + llList2String(parcel,0) + ".");
            }
        }
    }
 
    listen(integer channel, string name, key id, string message)
    {
        if(message == "Close")
        {
            RemoveListener();
        }
        else if(message == "Online")
        {
            status = TRUE;
            llSetTimerEvent(repeat);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"- Visitors -\nplease wait...", <0,1,0>, 1.0]);
            Dialog();
        }
        else if(message == "Offline")
        {
            status = FALSE;
            llSetTimerEvent(0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"- Visitors -\nOFFLINE", <1,0,0>, 1.0]);
        }
        else if(message == "Reset")
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"", <1,0,0>, 1.0]);
            llMessageLinked(LINK_SET, 1000, "RESET", "");
            llResetScript();
        }
        else if(message == "Parcel")
        {
            scanner = TRUE;
            llMessageLinked(LINK_SET, 1000, "RESET", "");
            scope = AGENT_LIST_PARCEL;
            s_info = message;
            Dialog();
        }
        else if(message == "Region")
        {
            scanner = FALSE;
            llMessageLinked(LINK_SET, 1000, "RESET", "");
            scope = AGENT_LIST_REGION;
            s_info = message;
            Dialog();
        }
        else if(message == "Greeter")
        {
            greeting = TRUE;
            Dialog();
        }
        else if(message == "Silent")
        {
            greeting = FALSE;
            Dialog();
        }
    }
 
    on_rez(integer Dae)
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"", <1,0,0>, 1.0]);
        llMessageLinked(LINK_SET, 1000, "RESET", "");
        llResetScript();
    }
}

*DS* Receptor Save v2.0.05

/*
    *DS* Receptor Save v2.0.05
    Dieses Script verwaltet die Besucher-Keys und ist aus diesem Grund moeglichst klein gehalten.
    Zudem istr eine Speicherkontrolle vorhanden, um eine Speicher-Ueberladung (Stack Heap Collision) zu vermeiden.
*/
 
key owner;
string date;
vector pos;
string region;
 
list visitor_list = [];
integer total = 0;
integer current = 0;
integer sametime = 0;
 
default
{
    state_entry()
    {
        owner = llGetOwner();
        date = llGetDate();
        pos = llGetPos();
        region = llGetRegionName();
    }
 
    link_message(integer sender_num, integer num, string msg, key id) 
    {
        if(num == 1000)
        {
            list temp = llParseString2List(msg, [" "], []);
            string cmd = llStringTrim(llList2String(temp, 0), STRING_TRIM);
            string data = llStringTrim(llList2String(temp, 1), STRING_TRIM);
 
            if(cmd == "COUNT")
            {
                // ↓ empfaengt vom Mainscript die Anzahl Keys und aktuallisiert den hoechststand
                current = (integer)data;
                if(current > sametime)
                {
                    sametime = current;
                }
            }
            else if(cmd == "KEYS")
            {
                if(!~llListFindList(visitor_list, [data])) // vergleicht den aktuellen Key mit denen in der Liste
                {
                    visitor_list += data;                       // unbekannter Key wird zur Liste hinzugefuegt
                    total = llGetListLength(visitor_list);      // aktuallisiert die Listen-Laenge
                    llMessageLinked(LINK_SET, 2000, data, "");  // sendet den Key zum Main-Script zurueck
 
                    // ↓ Diese Funktion verhindert eine Speicher Speicher-Ueberladung (Stack Heap Collision)
                    if(llGetFreeMemory() < 10000)
                    {
                        llInstantMessage(owner, "/me Low Memory: cleaning List\nVisitors today: " + (string)total);
                        visitor_list = [];
                    }
                }
                // ↓ aktuallisiert den Hovertext
                llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT,"Visitors - " + date +
                                                                   "\ncurrent: " + (string)current +
                                                                   "\nsame time: " + (string)sametime +
                                                                   "\nunique total: " + (string)total, <1,1,1>, 1.0]);
            }
            else if(cmd == "RESET")
            {
                // ↓ sendet die Statistik an den Besitzer per Instant Message
                llInstantMessage(owner, "Visitor Statistics for " + date +
                                        "\ncurrent: " + (string)current +
                                        "\nsame time: " + (string)sametime +
                                        "\nunique total: " + (string)total +
                                        "\nsecondlife:///app/teleport/" + llEscapeURL(region) +
                                                                    "/" + (string)(llRound(pos.x)) +
                                                                    "/" + (string)(llRound(pos.y)) +
                                                                    "/" + (string)(llCeil(pos.z)));
                llResetScript(); // resettet das Script
            }
        }
    }
}

*DS* Group Joiner

Dieses Script ist eigentlich nichts besonderes, aber ich ziehe es jedem Bot vor.

/*
    Dieses Script erzeugt einen Link zum oeffnen des Gruppenfensters wo sich der [Join] Button befindet.
    Voraussetzung zum joinen einer Gruppe ist die Gruppen-Einstellung 'Eintreten offen'.
*/
 
string Text = "Feel free and join our support group:";
string Group = "6fcac03d-2c09-d5a7-e73f-ff73e15965d4";
 
default
{
    state_entry()
    {
        // Auf Hovertext habe ich hier verzichtet, Bilder sind viel schoener.
    }
 
    touch_start(integer num_detected)
    {
        key Avatar = llDetectedKey(0);
        llRegionSayTo(Avatar, 0, Text + " secondlife:///app/group/" + Group + "/about");
    }
 
    on_rez(integer Dae)
    {
        llResetScript();
    }
}

*DS* Group Key

Bei folgendem Script handelt es sich um ein ueber 5 jahre altes Relikt. Ich habe es lediglich ausgegraben und auf den neusten Stand gebracht.

/*
    Mit diesem kleinen Script kannst du den Key (UUID) jeder Gruppe heraus finden.
    Dazu musst du lediglich das Object mit diesem Script in der gewuenschten Gruppe rezzen.
*/
 
default
{
    state_entry()
    {
        llSetText("Touch to learn\nGroup Key", <1,1,1>, 1.0);
    }
 
    touch_start(integer num_detected)
    {
        key Avatar = llDetectedKey(0);
 
        list Details = llGetObjectDetails(llGetKey(), [OBJECT_GROUP]);
        key Group_Key = llList2Key(Details, 0);
 
        if(Group_Key != NULL_KEY)
        {
            llRegionSayTo(Avatar, 0, "The Group Key is: " + (string)Group_Key);
        }
        else if(Group_Key == NULL_KEY)
        {
            llRegionSayTo(Avatar, 0, "Please set the Group for this object in EDIT under the GENERAL tab first.");
        }
    }
 
    on_rez(integer Dae)
    {
        llResetScript();
    }
}

*DS* LM Pin (Landmark Giver)

Dieses Script verwende ich in all meinen Shops und bin dadurch immer auf dem laufenden, welche Region neustartet und wie frequentiert der Shop ist. Fuer viele ist eine LOW TRAFFIK Location uninteressant, ich sehe das aber anders. Sehr oft beobachte ich, dass die Leute sich in den Satelite-Shops lediglich eine Landmark nehmen und dann im Mainstore erscheinen.

key owner;
 
// ### setz hier TRUE oder FALSE fuer ja oder nein ###
integer MESSAGE = TRUE; // Besitzer-Mitteilung
 
// ### setz hier TRUE oder FALSE fuer ja oder nein ###
integer THANKS  = TRUE;
string thx_msg  = "Thank you for visit *DaeSigns*."; // Besucher-Mitteilung
 
// ### setz hier TRUE oder FALSE fuer ja oder nein ###
integer TEXT    = TRUE;
string text     = "*DaeSigns*\nMainstore";  // Hovertext
vector color    = <0.8,0.6,0.2>;            // Hovertext-Farbe
float alpha     = 1.0;                      // Hovertext-Tranzparenz
 
///////////////////// SLurl /////////////////////
vector pos;
string region;
list parcel;
 
string SLurl(string region_name, vector pos)
{
    return "secondlife:///app/teleport/" + llEscapeURL(region_name) +
                                     "/" + (string)(llRound(pos.x)) +
                                     "/" + (string)(llRound(pos.y)) +
                                     "/" + (string)(llCeil(pos.z));
}
 
// ########## NOTHING TO DO UNDER THIS LINE ##########
default
{
    state_entry()
    {
        llSetMemoryLimit(20000);
        owner = llGetOwner();
 
        pos = llGetPos();
        region = llGetRegionName();
        parcel = llGetParcelDetails(pos, [PARCEL_DETAILS_NAME]);
 
        llSetText("",ZERO_VECTOR,0);
        if(TEXT)
        {
            llSetText(text, color, alpha);
        }
        llOwnerSay(llGetScriptName() + " memory: loaded [ " + (string)llGetUsedMemory() + " | " + (string)llGetMemoryLimit() + " ] limit");
    }
 
    touch_start(integer total_number)
    {
        key Avi = llDetectedKey(0);
        if(llGetInventoryNumber(INVENTORY_LANDMARK) > 0)
        {
            llGiveInventory(Avi,llGetInventoryName(INVENTORY_LANDMARK, 0));
 
            if(THANKS)
            {
                llSay(0, thx_msg);
            }
 
            if(MESSAGE)
            {
                llInstantMessage(owner, "/me on parcel '" + llList2String(parcel ,0) + 
                "' noticed, that the visitor " + llGetUsername(Avi) + " has taken a landmark. " + SLurl(region,pos));
            }
        }
    }
 
    changed(integer change)
    {
        if(change & CHANGED_REGION_START)
        {
            if(MESSAGE)
            {
                llInstantMessage(owner, "/me on parcel '" + llList2String(parcel ,0) + 
                "' noticed, that the region '" + region + "' has been restarted. " + SLurl(region,pos));
            }
        }
        if(change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
 
    on_rez(integer Dae)
    {
        llResetScript();
    }
}