Difference between revisions of "User:Daemonika Nightfire/Scripts/Schalter"

From Second Life Wiki
Jump to navigation Jump to search
(added descrptions to Umkehr-Schalter & Ampel-Schalter)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{DSNavSchool}}
==Schalter Einleitung==
==Schalter Einleitung==
Warum spreche ich hier von einem Schalter? Ganz einfach, weil es das ist.
Warum spreche ich hier von einem Schalter? Ganz einfach, weil es das ist.
Line 422: Line 423:
           Das entspricht in Zahlen 1 = !1; also 0, (oder anders herum).
           Das entspricht in Zahlen 1 = !1; also 0, (oder anders herum).


  Der einfacher Weechselschalter funktioniert ideal fuer zweifache Schaltung.
  Der einfache Wechselschalter funktioniert ideal fuer zweifache Schaltung.
  Doch moechtest du mehr als 2 Zustaende schalten, benoetigst du einen Counter.
  Doch moechtest du mehr als 2 Zustaende schalten, benoetigst du einen Counter.
   
   
Line 428: Line 429:
  counter++;
  counter++;
   
   
  Ein entsprechendes Beispiel fuidest du weiter unten in der Ampel-Schaltung.
  Ein entsprechendes Beispiel findest du weiter unten in der Ampel-Schaltung.


==Umkehr-Schalter (list)==
==Umkehr-Schalter (list)==

Latest revision as of 02:47, 3 January 2020

Schalter Einleitung

Warum spreche ich hier von einem Schalter? Ganz einfach, weil es das ist.

TRUE & FALSE sind Boolesche Variablen mit endlichen Werten.
Diese Schaltvariablen sind auf den Mathematiker George Boole im Jahr 1847 zurueck zu fuehren.
Gleichbedeutend mit 1 & 0 - ja & nein - richtig & falsch, koennen wir damit einen Status-Wechsel erzeugen.
Mehr Details hier: https://de.wikipedia.org/wiki/Boolesche_Variable

Du wirst feststellen, das viele Scripte doppelt aufgefuehrt sind.

Auf der linken Seite befindet sich die Standard Version. Auf der rechten Seite die Version mit einer globalen Funktion. Beide Versionen haben eine Daseinsberechtigung. Die globale Funktion hat den Vorteil, du musst dich im Script nicht wiederholen, sondern schreibst die Funktion nur einmal und greifst von jedem beliebigen Event aus darauf zu.

Um laestigen Chat-Spam zu vermeiden habe ich bei saetmlichen Beispielen die Status-Meldungen in einen Hovertext gesetzt. An den stellen wo sich der Hovertext befindet, kannst du natuerlich statt dessen jede beliebige Funktion ausfuehren.

touch

Der touch_start Event ist die einfachste Methode um die Funktionsweise eines Schalters zu verdeutlichen. Hier reagiert das Script sofort wenn du den Prim klickst.

Einfacher Schalter Schalter als globale Funktion
integer schalter = FALSE;

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        if(schalter == FALSE)
        {
            schalter = TRUE;
            llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
        }
        else if(schalter == TRUE)
        {
            schalter = FALSE;
            llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
        }
    }
}
integer schalter = FALSE;

SchalterFunktion()
{
    if(schalter == FALSE)
    {
        schalter = TRUE;
        llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
    }
    else if(schalter == TRUE)
    {
        schalter = FALSE;
        llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
    }
}

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        SchalterFunktion();
    }
}

listener

Fuer den Schalter im listen Event ist es notwendig beispielsweise /1schalte in den lokalen Chat zu tippen, damit das Script reagiert.

Einfacher Schalter Schalter als globale Funktion
integer schalter = FALSE;

default
{
    state_entry()
    {
        llListen(1, "", llGetOwner(), "");
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    listen(integer Channel, string Name, key ID, string Text)
    {
        if(Text == "schalte")
        {
            if(schalter == FALSE)
            {
                schalter = TRUE;
                llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
            }
            else if(schalter == TRUE)
            {
                schalter = FALSE;
                llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
            }
        }
    }
}
integer schalter = FALSE;

SchalterFunktion()
{
    if(schalter == FALSE)
    {
        schalter = TRUE;
        llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
    }
    else if(schalter == TRUE)
    {
        schalter = FALSE;
        llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
    }
}

default
{
    state_entry()
    {
        llListen(1, "", llGetOwner(), "");
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    listen(integer Channel, string Name, key ID, string Text)
    {
        if(Text == "schalte")
        {
            SchalterFunktion();
        }
    }
}

collision

Fuer diese collision Variante musst du mit deinem Avatar auf bzw. gegen den Prim laufen.

Bei einem Phantom Object mit llVolumeDetect genuegt es den Avatar durch den Prim zu bewegen.

Einfacher Schalter Schalter als globale Funktion
integer schalter = FALSE;

default
{
    state_entry()
    {
        // llVolumeDetect(TRUE); // Diese Funktion ist fuer phantom Objekte.
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    collision_start(integer num)
    {
        if(schalter == FALSE)
        {
            schalter = TRUE;
            llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
        }
        else if(schalter == TRUE)
        {
            schalter = FALSE;
            llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
        }
    }
}
integer schalter = FALSE;

SchalterFunktion()
{
    if(schalter == FALSE)
    {
        schalter = TRUE;
        llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
    }
    else if(schalter == TRUE)
    {
        schalter = FALSE;
        llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
    }
}

default
{
    state_entry()
    {
        // llVolumeDetect(TRUE); // Diese Funktion ist fuer phantom Objekte.
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    collision_start(integer num)
    {
        SchalterFunktion();
    }
}

timer

Der timer hingegen kommt voellig ohne interaktion mit Avataren aus. Hier tickt der timer im 5 Sekunden-Tackt und wechselt automatisch zwischen beiden Hovertexten hin und her.

Einfacher Schalter Schalter als globale Funktion
integer schalter = FALSE;

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
        llSetTimerEvent(5);
    }

    timer()
    {
        if(schalter == FALSE)
        {
            schalter = TRUE;
            llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
        }
        else if(schalter == TRUE)
        {
            schalter = FALSE;
            llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
        }
    }
}
integer schalter = FALSE;

SchalterFunktion()
{
    if(schalter == FALSE)
    {
        schalter = TRUE;
        llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
    }
    else if(schalter == TRUE)
    {
        schalter = FALSE;
        llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
    }
}

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
        llSetTimerEvent(5);
    }

    timer()
    {
        SchalterFunktion();
    }
}

sensor

Jetzt wird es kompliziert, der llSensorRepeat verwendet einen eigenen integrierten Timer und tickt in diesem Beispiel 1x pro Sekunde.

Es gibt natuerlich noch den llSensor, doch diese Funktion fuer das aktuelle Beispiel nicht ideal, weil sie fuer den gleichen Zweck mit einem Timer kombiniert werden muesste.

In diesem Beispiel wechselt der Status permanent im Secunden-Tackt, solange sich ein Avatar im Sensor-Bereich aufhaelt.

Einfacher Schalter Schalter als globale Funktion
integer schalter = FALSE;

default
{
    state_entry()
    {
        llSensorRemove();
        
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
        llSensorRepeat("", "", AGENT_BY_LEGACY_NAME, 3.0, PI, 1.0);
    }

    sensor(integer num_detected)
    {
        if(schalter == FALSE)
        {
            schalter = TRUE;
            llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
        }
        else if(schalter == TRUE)
        {
            schalter = FALSE;
            llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
        }
    }
}
integer schalter = FALSE;

SchalterFunktion()
{
    if(schalter == FALSE)
    {
        schalter = TRUE;
        llSetText("eingeschaltet, schalter ist nun TRUE", <0,1,0>, 1.0);
    }
    else if(schalter == TRUE)
    {
        schalter = FALSE;
        llSetText("ausgeschaltet, schalter ist nun FALSE", <1,0,0>, 1.0);
    }
}

default
{
    state_entry()
    {
        llSensorRemove();
        
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
        llSensorRepeat("", "", AGENT_BY_LEGACY_NAME, 3.0, PI, 1.0);
    }

    sensor(integer num_detected)
    {
        SchalterFunktion();
    }
}

Anders als bei den ersten beiden Sensor Beispielen verhaelt sich dieser Sensor etwas anders, doch das Ergebnis ist das gleiche.

Hier wechselt der Schalter nicht permanent, sondern setzt den Status wenn sich ein Avatar im Sensor-Bereich aufhaelt und erst dann wieder zurueck, wenn der Avatar den Sensor-Bereich verlaesst.

integer schalter = FALSE;

default
{
    state_entry()
    {
        llSensorRemove();
        
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
        llSensorRepeat("", "", AGENT_BY_LEGACY_NAME, 3.0, PI, 1.0);
    }

    sensor(integer num_detected)
    {
        if(schalter == FALSE)
        {
            schalter = TRUE;
            llSetText("eingeschaltet, Tuer ist geoeffnet", <0,1,0>, 1.0);
        }
    }
    
    no_sensor()
    {
        if(schalter == TRUE)
        {
            schalter = FALSE;
            llSetText("ausgeschaltet, Tuer ist geschlossen", <1,0,0>, 1.0);
        }
    }
}

Tips & Tricks

Jetzt besteht auch noch die Moeglichkeit vieles abzukuerzen und effizienter zu gestalten.
Da waere der leere integer als globale Variable, der Wert ist pauschal immer 0 (null).

 integer schalter;
Nun anstelle von TRUE und FALSE kannst du auch den Schalter und !Schalter (nicht schalter) abfragen.
Als Bolesche Variable kann der Wert nur das Gegenstueck, entweder 1 oder 0 sein.

 if(!schalter)
 {
    schalter = 1;
 }
 else if(schalter)
 {
    schalter = 0;
 }
Zu diesem Nicht-Schalter gibt es sogar noch einen Hack, der in Second Life einwandfrei fuer einfaches Schalt-Verhalten an/aus funktioniert.

Beispiel: Schalter = !Schalter;
          Das entspricht in Zahlen 1 = !1; also 0, (oder anders herum).
Der einfache Wechselschalter funktioniert ideal fuer zweifache Schaltung.
Doch moechtest du mehr als 2 Zustaende schalten, benoetigst du einen Counter.

integer counter = 0;
counter++;

Ein entsprechendes Beispiel findest du weiter unten in der Ampel-Schaltung.

Umkehr-Schalter (list)

Bei diesem Schalter verwende ich den Booleschen Wert 0 & 1 ganz einfach als index fuer den Stellenwert der Liste mit den Variablen.

Einfacher Schalter Schalter als globale Funktion
integer schalter;

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        list text = ["OFF","ON", <1,0,0>, <0,1,0>];
        schalter = !schalter;
        
        llSetText(llList2String(text, schalter), llList2Vector(text, schalter+2), 1.0);
    }
}
integer schalter;

SchalterFunktion(integer index)
{
    list text = ["OFF","ON", <1,0,0>, <0,1,0>];
    llSetText(llList2String(text, index), llList2Vector(text, index+2), 1.0);
}

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        schalter = !schalter;
        SchalterFunktion(schalter);
    }
}

Ampel-Schalter (list)

Auch dieser Schalter verwendet eine Liste mit Variablen, doch wird hier der index nicht mit einem Booleschen Wert bestimmt, sondern mit einem Counter der Reihe nach geschaltet.

Einfacher Schalter Schalter als globale Funktion
integer counter = 0;

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        list text = ["Rot", "Gruen", "Blau", <1,0,0>, <0,1,0>, <0,0,1>];
        llSetText(llList2String(text, counter), llList2Vector(text, counter+3), 1.0);
        
        counter++;
        if(counter > 2)
        {
            counter = 0;
        }
    }
}
integer counter = 0;

SchalterFunktion(integer index)
{
    list text = ["Rot", "Gruen", "Blau", <1,0,0>, <0,1,0>, <0,0,1>];
    llSetText(llList2String(text, index), llList2Vector(text, index+3), 1.0);
}

default
{
    state_entry()
    {
        llSetText("Reset, schalter startet ausgeschaltet", <1,1,1>, 1.0);
    }

    touch_start(integer total_number)
    {
        SchalterFunktion(counter);
        
        counter++;
        if(counter > 2)
        {
            counter = 0;
        }
    }
}