• Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
  • Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
  • Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Sie geben Einwilligung zu unseren Cookies, wenn Sie unsere Webseite weiterhin nutzen.

Scripten Lernen (Deutsch)

Wer hat Interesse, Scripte zu verstehen?


  • Umfrageteilnehmer
    19
  • Umfrage geschlossen .
Vielen Dank surini fuer den Link und vielen Dank an Uli fuer die tolle Aufnahme.

Manche haben schon festgestellt, das der Schwierigkeitsgrad nun langsam beginnt zu steigen, dennoch versuche ich es noch so einfach wie nur irgend moeglich zu halten.

Wir haben uns drauf geeinigt vorerst bei dem Thema Kommunikation zu bleiben.
Fuer kommenden Sonntag habe ich geplant ein einfaches Menue zu erstellen, womit wir mehr als 2 Texturen auf unterschiedlichen Faces eines Empfaengers einstellen koennen.
Dazu benoetigen wir einen uns schon bekannten Event, den listener(... inclusive llListen(... plus einem neuen Befehl llDialog(... und wir arbeiten wieder mit listen list Liste = [];

Der naechste Kurs findet am 29.04.2018 um 20 Uhr statt.
Danach aendern wir den Rytmuss auf 14 taegig sonntags gleiche Zeit
Schulbus: Bitte einsteigen.

Das Thema fuer den Kurs voraussichtlich am 13.05.2018 um 20 Uhr ist aehnlich dem des kommenden Wochenendes, allerdings erstellen wir ein Object mit mehreren Flaechen zum klicken, womit wir ein weiteres Object umtexturieren koennen.
Das bedeutet, auf kurz oder lang sind die Kursteilnehmer dazu in der Lage selbt ihren eigenen FULLPERM Textur Changer Hud fuer eigene Kleidung zu erstellen.

LG
Dae
 
huhu,

vielen Dank fuer eure Gedult. :)
Sagt mal, geht das nur mir so oder rennt die Zeit uns wirklich immer weg?

Keine Sorge, es ist noch nicht Hopfen und Malz verloren. Beim naechsten Kurs werden wir den Stoff von heute noch mal in Ruhe durch gehen.
In der Zwischenzeit habt ihr ja genug Zeit euch die aktuellen Scripte genau anzusehen, probieren was geht und einfach mal bissl rum spielen.
Macht euch keine Gedanken darum wenn was kaputt geht, die Scripte sind Fullperm, einfach loeschen und neu rezzen. ;)

Vor dem Kurs von heute hatte ich schon die Befuerchtung, das wir nicht alles schaffen, weil das Thema doch sehr umfangreich ist.
Nichts desto Trotz wuerde ich mir wuenschen, das mehr Fragen gestellt werden.
Keine Frage kann so dumm sein, das sie nicht ordentlich beantwortet wird.
Man darf nicht vergessen, es ist ein Anfaengerkurs, wenn man etwas nicht versteht sollte man nachhaken, aber dazu haben wir ja im naechsten Kurs die Gelegenheit. :)

Alles in Allem macht es mir der Kurs immer noch Freude.
In diesem Sinne, ich freue mich schon auf den naechsten Kurs.

LG
Dae
 
Vielen Dank Uli, ich finde deine Videos immer sehr toll.


Bei dem Ueberraschungstest war es nicht zwingend wichtig fertig zu werden oder alles richtig zu haben.
Aus diesem Grund habe ich auch so gut wie gar nicht geholfen, ich wollte nur sehen wer noch schwierigkeiten hat die Uebersicht zu behalten.

Alles in allem sind die meisten mit diesem Test doch recht gut zurecht gekommen, auch wenn die Handhabung sich anfangs etwas schwierig gestaltet hat.


Beim naechsten Kurs gehts ans Eingemachte.
Das wird noch etwas umfangreicher und komplizierter, da wir auch Permissions beruecksichtigen muessen.
Das klingt aber dramatischer als es ist, wichtig ist das wir die einzelnen Komponenten die wir verbauen moechten auch verstehen. Darum werde ich diesbezueglich die Bestandteile splitten und vorab hier im Forum veroeffentlichen.

Entsprechende Beitraege folgen in kuerze.

In diesem Sinne, vielen Dank und viel Spass bei allen zukuenftigen Kursen.

LG
Dae
 
Wie versprochen, hier nun der erste Teil von 4 Lektionen

Lektion [1 / 4 ]

llDetectedLinkNumber(integer Number); ist in folgenden Events verwendbar:
collision, collision_start, collision_end, sensor, touch, touch_start, touch_end
Code:
llDetectedLinkNumber(0);
integer LinkNumber = llDetectedLinkNumber(0);
Mit diesem Befehl ist es moeglich, zu erkennen, welcher Prim (Link) im LinkSet geklickt wurde.


llDetectedTouchFace(integer Index); ist in folgenden Events verwendbar:
touch, touch_start, touch_end
Code:
llDetectedTouchFace(0);
integer LinkFace = llDetectedTouchFace(0);
Dieser Befehl dient dazu, zu ermitteln welche Flaeche (Face) eines Prims (Link) geklickt wurde.


llGetLinkName(integer LinkNumber); verwendbar ueberall, benoetigt jedoch eine aktuelle LinkNummer:
Code:
llGetLinkName(LinkNumber);
string LinkName = llGetLinkName(LinkNumber);
Sobald eine LinkNummer bekannt ist, kann mittels deises Befehls der LinkName ermittelt werden.


Fuer folgendes Script, verlinkt bitte mehrere Wuerfel und benennt jeden mit einen individuellen Namen. Anschliessend erzeugt im HauptPrim (RootLink) ein New Script mit folgenden Befehlen:
Code:
default
{
    state_entry()
    {
      
    }

    touch_start(integer total_number)
    {
        integer LinkNumber = llDetectedLinkNumber(0);
        integer LinkFace = llDetectedTouchFace(0);
        string LinkName = llGetLinkName(LinkNumber);
      
        llSay(0, "\nLinknummer = " + (string)LinkNumber +
                 "\nSeite = " + (string)LinkFace +
                 "\nLinkname = " + LinkName);
    }
}

In diesem Script ist die Reihenfolge sehr wichtig. Ihr koennt niemals den LinkNamen vor der LinkNummer ermitteln.

Wie ihr sehen koennt, habe ich im llSay viele seltsame Zeichen eingebaut, die eigentlich nicht im Chat erscheinen. Da waere das + und die kombination \n im Befehl.
Das \n dient dazu, mitten im Text eine neue Zeile zu beginnen, dabei ist es nicht erforderlich leerzeichen davor oder dahinter anzubringen.

Das + wird verwendet, um veraenderbare Variablen im Text zu aktuallisieren.
Dazu macht man einfach einmal ein Gaensefuesschen an die Stelle wo man den Text fuer die Variable unterbrechen moechte und gleich hinter der variable geht es in umgekehrter Reihenfolge weiter, wenn man dort weitere texte benoetigt.
Bitte denkt daran, saemtliche Variablen die nicht von vornherein schon strings sind, zuerst mittels (string) ohne Leerschritt direkt davor zu einem string umzuwandeln.

Wenn ihr nun das Script im Root liegen habt, klickt einfach mal die jeweiligen Wuerfel auf unterschiedlichen Flaechen und achtet auf den Chat.

LG
Dae
 
Die zweite Lektion ist wieder etwas einfacher.

Lektion [ 2 / 4 ]

llLoadURL(key avatar, string message, string url); ist ueberall verwendbar wo es aufgerufen werden kann.
Die erste Variable beschreibt den Avatar, fuer wen sich die Webseite oeffnen soll.
Die zweite Variable ist eine individuelle Message innerhalb der sich oeffnenden Abfrage, ob ihr die Webseite oeffnen wollt.
Bei der dritten Variable wird in Gaensefuesschen die URL einer Webseite angegeben.

Im folgenden Script verwende ich die URL einer Webseite als globale Variable und gebe im Befel selber nur den Variable-Namen an.
Der Avatar fuer den sich die URL oeffnen soll wird in diesem Fall automatisch mittels touch per llDetectedKey(0); ermittelt und im Befehl eingetragen.

Code:
string URL = "https://marketplace.secondlife.com/de-DE/stores/30293";

default
{
    state_entry()
    {
     
    }

    touch_start(integer total_number)
    {
        key User = llDetectedKey(0);
        llLoadURL(User, "Marketplace", URL);
    }
}

PS: Wenn mit diesem Befehl versucht wird zu schnell hintereinander eine Webseite zu oeffnen, wird der Vorgang vom Server automatisch ausgebremst. Im Chat erscheint dann folgende Fehlermeldung:
[02:03:21] *DS* Script Kurs (load url): Too many llLoadURL requests. Throttled until average falls.


Viel Spass beim experimentieren. :)

LG
Dae
 
Auwaia, also die Wiki Erklaerung fuer dieses beispiel ist alles andere als Anfaengerfreundlich geschrieben.
Wer sich gern Migraene abholen moechte, bitte hier entlang: http://wiki.secondlife.com/wiki/LlParseString2List

Lektion [ 3 / 4 ]

Ich versuche es mal etwas einfacher, ohne verwirrenden wichtig aussehenden Schnik Schnak.
list llParseString2List(string src, list separators, list spacers); ist ueberall anwendbar.
Mit Hilfe dieses Befehls, lassen sich Strings zu einer Liste zerlegen und die Elemente einzeln abrufen.
Parse String 2 List bedeutet im groben Vergleiche einen String als Liste.
Bei der ersten Variable handelt es sich um den vollstaendigen String.
Die zweite Variable steht duer die trennung der jeweiligen Elemente. Haeufig werden Leerschritte verwendet. Der Seperator kann natuerlich alles sein, doch fuer unsere Zwecke reicht vorerst der [" "] Leerschritt.
Variable Nummer 3 trennt die einzelnen Elemente an der angegebenen Stelle. Habe ich allerdings noch nie benoetigt. Deshalb verwende ich immer eine leere [] Liste.

Im folgenden Beispiel lege ich einen String Global an, um das Experimentieren zu erleichtern.
Der String besteht aus 2 Woertern, Wort 1 = Text, Wort 2 = 1
Da sich beide Elemente im Selben String befinden ist die Zahl 1 in diesem Fall kein Integer.

Code:
string IrgendEinText = "Text 1";

default
{
    state_entry()
    {
   
    }

    touch_start(integer total_number)
    {
        list ParsedName = llParseString2List(IrgendEinText, [" "], []);
        string Name = llList2String(ParsedName, 0);
        string Nummer = llList2String(ParsedName, 1);
   
        llSay(0, "IrgendEinText erster Teil: " + Name);
        llSay(0, "IrgendEinText zweiter Teil: " + Nummer);
    }
}

Bist zu 8 Elemente lassen sich zu einer Liste parsen.
Das bedeutet, ihr koennt ganze Saetze mit bis zu 8 Woertern hiermit zerlegen.
Dazu wird dann lediglich fuer jedes Element ein llList2String von 0 - 7 Benoetigt.

llList2String(list VariablenListe, integer Stellenwert); ist gleich unter der list parse verwendbar.
Die erste Variable ist die Liste, welche ihr mit llParseString2List anlegt.
Mit der zweiten Variable bestimmt ihr den Stellenwert, welchen ihr abrufen moechtet.

Hier noch ein Beispiel mit 8 woertern:
Code:
string IrgendEinText = "Ein ganzer Text bestehend aus acht einzelnen woertern";

default
{
    state_entry()
    {
       
    }

    touch_start(integer total_number)
    {
        list ParsedName = llParseString2List(IrgendEinText, [" "], []);
        string text1 = llList2String(ParsedName, 0);
        string text2 = llList2String(ParsedName, 1);
        string text3 = llList2String(ParsedName, 2);
        string text4 = llList2String(ParsedName, 3);
        string text5 = llList2String(ParsedName, 4);
        string text6 = llList2String(ParsedName, 5);
        string text7 = llList2String(ParsedName, 6);
        string text8 = llList2String(ParsedName, 7);
       
        llSay(0, "IrgendEinText erster Teil: " + text1);
        llSay(0, "IrgendEinText zweiter Teil: " + text2);
        llSay(0, "IrgendEinText dritter Teil: " + text3);
        llSay(0, "IrgendEinText vierter Teil: " + text4);
        llSay(0, "IrgendEinText fuenftrer Teil: " + text5);
        llSay(0, "IrgendEinText sechster Teil: " + text6);
        llSay(0, "IrgendEinText siebter Teil: " + text7);
        llSay(0, "IrgendEinText achter Teil: " + text8);
    }
}


Auch hier wuensche ich euch viel Spass beim experimentieren.

LG
Dae

Falls zu dieser Funktion noch Fragen offen sind, duerfen sie gerne hier im Thread gestellt werden.​
 
Zuletzt bearbeitet:
OK, es ist schon sehr spaet.
Im letzten Beitrag habe ich mich vertan.
Bei dem Limit von 8 Seperatoren und 8 Spacern ist nicht gemeint, das man nur 8 Elemente aus einem String filtern kann, sondern das man maximal 8 verschiedene Seperatoren und 8 verschiedene Spacer gleichzeitig in einem Befehl nutzen kann. Die Laenge des Strings spielt dabei keine Rolle.

Das wuerde dann so aussehen:
Code:
llParseString2List(IrgendEinText, [" ", "=","@","€","&","$","§","%"], []);
In der Regel reicht mir jedoch nur ein Seperator.

LG
Dae
 
Parse String 2 List bedeutet im groben Vergleiche einen String als Liste.
Darf ich zum Verständnis beitragen (oder auch nicht).
Die Funktion erstellt (Vergleich scheint mir hier irreführend) eine Liste vom String, in der die einzelnen Teile des Strings als Listenelemente vorhanden sind.
Aufgeteilt wird an Hand des Separators (Trennzeichen), selbiger ist dann in der Liste nicht mehr vorhanden.
 
Du hast recht, ich habe mal einen anderen Translator verwendet und bekam gleich viel sinnvollere angebote fuer das Wort Parse.
Vielleicht hatte ich letzte Nacht auch nur einen Anfall geistiger Umnachtung. :)

Parse = zerlegen, analysieren, zergliedern, aufgliedern, gliedern, verstehen

LG
Dae
 
Aha - Automatübersetzer sind immer was unterhaltsames und macht auch manche Wortwahl für mich verständlich.
Ich würde für den Scriptkurs anbieten, den manuellen Übersetzer zu spielen, wenn ich damit was beitragen kann.
Bin allerdings nicht immer am Sonntag zur Verfügung.
Sehr gute Erfahrungen hab ich auch mit diesem Übersetzer: https://www.deepl.com/translator
 
Vielen Dank Wolwaner, das ist eine tolle Idee.
Bei den Funktionen weiss ich zwar was sie machen und wie ich damit umgehen kann, aber bei manchen Begrifen tu ich mich schon etwas schwer die sinngemaess zu uebersetzen.

Du musst dir vorstellen, bevor ich nach Second Life kam, habe ich kein Wort English verstanden und habe mir alles selbst mit learning by doing bei gebracht.
Auch das Scripten habe ich voellig Autodidakt gelernt. Dazu habe ich damals beinahe jedes Freebie Script studiert welches ich in die Finger bekam und habe alles ausprobiert wie ich es aktuell hier in den Lektionen gesplittet habe.

So wie ich die Lektionen hier aufgeteilt habe, ist es quasi ein Spiegel dessen was ich vor 10 Jahren gemacht habe, um das Scripten zu verstehen.
Die Lektion 4 werde ich wohl erst am Wochenende schaffen, denn dazu muss ich ein wenig weiter ausholen. Auch wenn das Ergebniss wenig spektakulaer erscheint, muss man dennoch einiges beachten und lokale Situationen beruecksichtigen.

LG
Dae
 
Ich hoffe, meine Anregungen wurden nicht als herbe Kritik verstanden und es ist keinesfalls eine Rechtfertigung Deinerseits nötig, Du machst das prima!

Ich bin begeistert von
  • der Art, wie Du das machst (werde ich mir für einen neuen Kurs abkupfern ....)
  • Deinem Einsatz, das alles selber zu erlernen
  • dem Vorhaben, wochenlang Wissen weiter zu geben - script ist ja doch eine langwierige Sache.
Also wenn ich was dazu tun kann: Inworld nach Vereinbarung, E-Mail: Wolwaner_Jervil@a1.net
 
Vielen Dank und keine Sorge, das habe ich keineswegs als herbe Kritik verstanden. :)
Im Gegenteil, ich denke ich kann sehr gut mit Kritik umgehen und versuche moeglichst immer was daraus zu lernen.
Wenn mir etwas gegen den Strich geht, wirst es schon merkten. Dann bin ich nicht ganz so lieb, nett und freundlich.
Diejenigen die mich hier im Forum schon seit jahren kennen wissen das. ;)

LG
Dae
 
Zuletzt bearbeitet:
Lektion [ 4 / 4 ]

Auf Grund der Komplexitaet dieser Lektion muss ich die Bestandteile erst einmal aufteilen.

1.)
llGetAttached(); gibt den integer des Attachpoints (Anhaengepunkt) wieder.
Diesen Befehl kann man auch wunderbar dazu verwenden zu pruefen, ob ein Object am Avatar angehangen, oder auf dem Boden gerezzt wurde.

Mit folgendem Beispiel koennt ihr es selbst testen.
Code:
default
{
    state_entry()
    {
    
    }
 
    on_rez(integer Dae)
    {
        if(llGetAttached() == 0)
        {
            llSay(0, "Auf dem Boden gerezzt.");
        }
        else if(llGetAttached() != 0)
        {
            llSay(0, "Am Avatar angezogen.");
        }
    }
}
Beachtet die unterschiedlichen Fragen der jeweiligen if im on_rez(... Event.
Kann der Befehl keinen Attachpoint festgestellen, wird eine 0 zurueck gegeben.
Wird jedoch ein Attachpoint festgestellt, wird die jeweilige Nummer des Attachpoints zurueck gegeben, also nicht 0. Darum frage ich einfach den ausschluss der 0 ab, weil ich ja nicht weiss um welchen Attachpoint es sich handelt. ;)

2.)
Schauen wir uns nun mal den attach(key AvatarID) Event an.
Dieser Event erkennt beim Attachen (anziehen) den Key (Avatar UUID) des Traegers.
Hier kann man sehr bequem vergleichen, ob sich der Besitzer geaendert hat.
Code:
key Owner;

default
{
    state_entry()
    {
        Owner = llGetOwner();
    }
 
    attach(key AvatarID)
    {
        if(AvatarID != Owner)
        {
            llResetScript();
        }
    }
}

Bitte fuer Attachments auf keinen Fall den Changed Event mit der CHANGED_OWNER Option verwenden, der Funktioniert ausschliesslich bei gerezzten Objecten, die als Original verkauft werden und Inworld den Besitzer wechseln, ohne ins Inventar genommen zu werden. Bei Objecten die ueber das Inventar weiter gegeben werden, wird der Changed Event ueberhaupt nicht ausgeloest.


3.)

llRequestPermissions(key AvatarID, PERMISSION_ATTACH ); fragt nach Erlaubniss, in diesem Fall die Erlaubniss ein Attachment an oder auszuziehen.
Fuer diese Anfrage ist der Event run_time_permissions(integer perm) zwingend erforderlich, da sonst eine Fehlermeldung auftreten wuerde.
Ist die Erlaubniss gegeben, kann man mit dem Befehl llDetachFromAvatar(); das Object vom Avatar abnehmen (ausziehen)

Im folgenden Script frage ich im run_time_permission Event mit einer if ab, ob die Erlaubniss erteilt wurde.
Code:
key Owner;

default
{
    state_entry()
    {
        Owner = llGetOwner();
        llRequestPermissions(Owner, PERMISSION_ATTACH );
    }
 
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_ATTACH)
        {
            llOwnerSay("ready...");
        }
    }

    touch_start(integer total_number)
    {
        llDetachFromAvatar();
    }
}
Wenn ihr nun einen Wuerfel mit diesem Script anzieht, und ihn dann anklickt, wird er euch wieder ausgezogen.


4.)
Nun kombinieren wir mal die ersten 3 Beispiele zu einem einzigen Script.
Die wichtigen Befehle fuer das ausziehen habe ich in eine if mit der Abfrage ob es angezogen ist gesetzt, da es keinen Sinn macht das auszufuehren, wenn es am Boden liegt.

Mit Reset:
Code:
key Owner;

default
{
    state_entry()
    {
        Owner = llGetOwner();
        if(llGetAttached() != 0)
        {
            llRequestPermissions(Owner, PERMISSION_ATTACH );
        }
    }
 
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_ATTACH)
        {
            llOwnerSay("ready...");
        }
    }

    touch_start(integer total_number)
    {
        if(llGetAttached() != 0)
        {
            llDetachFromAvatar();
        }
    }
 
    attach(key AvatarID)
    {
        if(AvatarID != Owner)
        {
            llResetScript();
        }
    }
 
    on_rez(integer Dae)
    {
        llResetScript();
    }
}

Dieses Beispiel dient dem Verstaendniss.
Es kommt vor, das man diese Funktionen jedoch nicht mit Reset verwenden kann, weil man eventuell bestimmte Einstellungen oder temporaere Werte erhalten will.
In diesem Fall muss man wiefolgt vorgehen.

Ohne Reset:
Code:
key Owner;

default
{
    state_entry()
    {
        Owner = llGetOwner();
        if(llGetAttached() != 0)
        {
            llRequestPermissions(Owner, PERMISSION_ATTACH );
        }
    }
 
    run_time_permissions(integer perm)
    {
        if(perm & PERMISSION_ATTACH)
        {
            llOwnerSay("ready...");
        }
    }

    touch_start(integer total_number)
    {
        if(llGetAttached() != 0)
        {
            llDetachFromAvatar();
        }
    }
 
    attach(key AvatarID)
    {
        if(AvatarID != Owner)
        {
            Owner = llGetOwner();
            if(llGetAttached() != 0)
            {
                llRequestPermissions(Owner, PERMISSION_ATTACH );
            }
        }
    }
 
    on_rez(integer Dae)
    {
        //llResetScript();
    }
}
Ihr werdet feststellen, das ich lediglich im Attach Event das Reset raus geschmissen und den Inhalt des State Entry dort hinein kopiert habe. Allerdings habe ich den State Entry nicht geleert, eben weil man das Script immer noch manuell mit dem Baumenue resetten kann und dann wird der Attach Event nunmal nicht ausgeloest, aber der State Entry. ;)
Das Reset im On Rez Event habe ich ganz einfach nur deaktiviert, wenn der Event ueberhaupt nicht benoetigt wird, kann man ihn auch komplett loeschen.

Im naechsten Inworld Kurs lernen wir, wie wir alle 4 Lektionen sinnvoll in einem einzigen Script miteinander kombinieren. Darum bitte ich euch, mit allen 4 Lektionen zu experimentieren.

LG
Dae
 
Zuletzt bearbeitet:
Script Unterricht

Der naechste Termin ist am Sonntag den 27.05.2018 um 20 Uhr.
An diesem Abend moechte ich mit euch den Touch basierenden Textur Changer Hud ohne Menue basteln.
Alle Lektionen 1 - 4 sind dazu erforderlich, um diesen Hud vollstaendig zu verstehen.

HUD Hintergrund.jpg

Bitte schaut euch folgende Beispiele aus diesem Thread kommende Woche genau an:
  1. Lektion [ 1 / 4 ] Scripten Lernen (Deutsch)
  2. Lektion [ 2 / 4 ] Scripten Lernen (Deutsch)
  3. Lektion [ 3 / 4 ] Scripten Lernen (Deutsch)
  4. Lektion [ 4 / 4 ] Scripten Lernen (Deutsch)
Am Sonntag treffen wir uns dann Inworld auf Bay of Surreality und ich frag ab, ob ihr alle Hausaufgaben gemacht habt. ;)

LG
Dae
 

Users who are viewing this thread

Zurück
Oben Unten