GridTalk.de

Normale Version: (Fast) weiche Bewegung - Tour Skript
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Seiten: 1 2
Basierend auf dem VogelSkript von Kayaker Magic (zu finden hier) hab ich mal ein Tour-Skript gebastelt, das Wegpunkte abfährt, auch mal etwas verweilt und/oder Text ausgibt. Im OSgrid hab ich damit fast flüssige Bewegungen hinbekommen, auf meiner Insel leider nicht weils da momentan ziemlich laggt. Das hängt wohl auch von der Grösse des Objektes ab. Nötig ist dazu nur eine Notecard namens config, wo die Wegpunkte in der Form
DRIVE = <Position> = <Rotation>
drinstehen. Die letzte Position sollte natürlich die Ausgangspostion sein.
Unter dem jeweiligen Wegpunkt kann auch noch eine Pause angegeben werden.
PAUSE = Sekunden
Und/oder auch ein Text der ausgegeben werden soll.
TEXT = Text
Mit der Konstanten TIME kann im Skript eingestellt werden wie schnell sich das Objekt bewegt, mit 1.0 ist es etwa 1 Meter/Sekunde. Grösser = schneller, aber auch mehr Ruckeln.
Und hier das Skript:
Code:
// Tour script by Rebekka Revnik
// it's free for everyone, no restrictions
// you may delete my name and claim it as your own script
// but if you give credit it would be nice :-)

// the first part is not mine, thanks and credits goes to Kayaker :-)

// Single Framed (SF) motion without llKeyframedMotion
// original script : Kayaker Magic
// from: http://forums.osgrid.org/viewtopic.php?f=5&t=4577
// minor changes by me

vector      SF_spos;        //start position
rotation    SF_srot;        //starting rotation
float       SF_stime;       //starting time
vector      SF_epos;        //ending position
rotation    SF_erot;        //ending rotation
float       SF_seconds;     //time to move that distance
integer     SF_target=-1;      //handle of last target position

SFrame()
{
    SF_spos=llGetPos();
    SF_srot=llGetRot();
    SF_stime=llGetTime();
    SF_epos = llList2Vector(Points, Count);
    SF_erot = llList2Rot(Rots, Count);
    SF_seconds=llVecDist(SF_epos, llGetPos()) / TIME;
    rotation t=<SF_srot.x-SF_erot.x,SF_srot.y-SF_erot.y,SF_srot.z-SF_erot.z,SF_srot.s-SF_erot.s>;
    if ((t.x*t.x + t.y*t.y + t.z*t.z + t.s*t.x)>0.5) SF_erot = <-SF_erot.x,-SF_erot.y,-SF_erot.z,-SF_erot.s>;
    llTargetRemove(SF_target);
    SF_target=llTarget(SF_epos, 0.1);
}

integer SFnotat()
{
    if (SF_target== -1) return TRUE;
    float time=llGetTime();
    time = (time-SF_stime)/SF_seconds;
    if (time>1.0)
    {
        llTargetRemove(SF_target);
        SF_target=-1;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,SF_epos,PRIM_ROTATION,SF_erot]);
        return TRUE;
    }
    float emit= 1.0-time;
    vector pos=SF_epos*time+SF_spos*emit;
    rotation rot = <
        SF_erot.x*time+SF_srot.x*emit,
        SF_erot.y*time+SF_srot.y*emit,
        SF_erot.z*time+SF_srot.z*emit,
        SF_erot.s*time+SF_srot.s*emit
            >;
    emit = llSqrt(rot.x*rot.x+rot.y*rot.y+rot.z*rot.z+rot.s*rot.s);
    rot = <rot.x/emit,rot.y/emit,rot.z/emit,rot.s/emit>;
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,pos,PRIM_ROTATION,rot]);
    return FALSE;
}

// ab hier hab ich das geschrieben :-)

// Mach dir eine Notecard mit den folgenden Einträgen
// Gross/Kleinschreibung ist nicht wichtig, also DRIVE ist genauso gut wie drive oder Drive

// DRIVE = Position = Rotation        die Wegpunkte eben, mit Position und Rotation

// nach dem Wegpunkt (muss aber nicht sein)

// PAUSE = Sekunden                    hält das Objekt ne Weile an
// TEXT = text                        sagt den Text im Chat

// now that's my part :-)

// Make a notecard with the folling entries
// it's not case sensitive, for example drive is accepted as DRIVE or Drive

// DRIVE = Position = Rotation        the waypoints with given params

// after the waypoint (optionally but but not required)

// PAUSE = seconds                    makes the object to stay for a while
// TEXT = text                        says the text in chat

// wie es oben steht, die Schlüsselwörter
// as above, the keywords
string DRIVE = "drive";
string PAUSE = "pause";
string TEXT = "text";
// Name der Notecard
// name of the notecard
string NCNAME = "config";
// Trennzeichen für die Schlüsselwörter
// separator for keywords
string SEPARATOR = "=";
// wie schnell sich das Objekt bewegt
// 1 ist ungefähr 1 Meter pro Sekunde
// Grösser = schneller, aber auch mehr ruckeln
// how fast your object will move
// 1 means appr. 1 m per second
// a greater number ist faster but less smoothly
float TIME = 1.0;
// Stell es auf TRUE, dann kommen Infos im Chat über die Wegpunkte
// set it to TRUE to get informations about the waypoints in chat
integer DEBUG = FALSE;
// Wähle die Sprache, ich kann nur die beiden unten sprechen
// 0 = deutsch, 1 = englisch
// choose language, I speak only the two below
// 0 for german, 1 for english
integer LANGUAGE = 0;

list Points;
list Rots;
list Pause;
list Text;
integer NCLine;
key NCid;
integer Count;

// liest ein Zeile aus der Notecard und speichert sie
// reads a notecard line and saves it
Read(string data)
{
    list l = llParseString2List(data, [SEPARATOR], []);
    string s1 = llToLower(llStringTrim(llList2String(l, 0), STRING_TRIM));
    vector v1 = (vector)llToLower(llStringTrim(llList2String(l, 1), STRING_TRIM));
    rotation r1 = (rotation)llToLower(llStringTrim(llList2String(l, 2), STRING_TRIM));
    integer x;
    if(s1 == DRIVE)
    {
        if(v1 != ZERO_VECTOR)
        {
            Points += [v1];
            Rots += [r1];
            Pause += [0];
            Text += [""];
        }
    } else if(s1 == PAUSE)
    {
        x = llGetListLength(Pause) - 1;
        Pause = llListReplaceList(Pause, [(float)llToLower(llStringTrim(llList2String(l, 1), STRING_TRIM))], x, x);

    } else if(s1 == TEXT)
    {
        x = llSubStringIndex(data, SEPARATOR);
        data = llDeleteSubString(data, 0, x);
        x = llGetListLength(Text) - 1;
        Text = llListReplaceList(Text, [llStringTrim(data, STRING_TRIM)], x, x);
    }
}

// Sagt was in der Notecard steht (TEXT = text), ohn den Objektnamen
// es muss aber ein Leerzeichen drin sein und mindestens zwei Wörter haben
// sonst kommt nur der normale Chat mit dem Objektnamen
// says what you wrote in the notecard (TEXT = text) without the object name
// it has to be a space in it and at least two words
// otherwise you'll get only the normal chat with the object name
Say(string s)
{
    string s1 = llGetObjectName();
    integer x = llSubStringIndex(s, " ");
    if(x != -1)
    {
        string s2 = llGetSubString(s, 0, x - 1);
        s = llDeleteSubString(s, 0, x -1);
        s = "/me" + s;
        llSetObjectName(s2);
    }
    llSay(0, s);
    llSetObjectName(s1);
}

default
{
    state_entry()
    {
        llSetText("", <1,1,1>, 1.0);
        Points = [];
        Rots = [];
        Pause = [];
        Text = [];
        if(llGetInventoryType(NCNAME) == INVENTORY_NONE)
        {
            if(LANGUAGE == 0) llOwnerSay("Keine config-NC gefunden.");
            else if(LANGUAGE == 1) llOwnerSay("No config nc found.");

        } else
        {
            if(LANGUAGE == 0) llOwnerSay("Lese config, bitte warten...");
            else if(LANGUAGE == 1) llOwnerSay("Reading config nc, please wait...");
            NCLine = 0;
            NCid = llGetNotecardLine(NCNAME, NCLine++);
        }
    }
    dataserver(key requested, string data)
    {
        if(requested == NCid)
        {
            if(data != EOF)
            {
                Read(data);
                NCid = llGetNotecardLine(NCNAME, NCLine++);
            } else
            {
                if(LANGUAGE == 0) llOwnerSay("Fertig.");
                else if(LANGUAGE == 1) llOwnerSay("Ready.");
                if(llGetListLength(Points) == 0)
                {
                    if(LANGUAGE == 0) llOwnerSay("Keine Wegpunkte gefunden.");
                    else if(LANGUAGE == 1) llOwnerSay("No waypoints found.");
                }
                else
                {
                    if(LANGUAGE == 0) llOwnerSay((string)llGetListLength(Points) + " Wegpunkte gelesen.");
                    else if(LANGUAGE == 1) llOwnerSay((string)llGetListLength(Points) + " waypoints read.");
                    state running;
                }
            }
        }
    }
}

state running
{
    state_entry()
    {
        if(LANGUAGE == 0) llSetText("Sitze und berühre mich", <1,1,1>, 1.0);
        else if(LANGUAGE == 1) llSetText("Sit down and touch me", <1,1,1>, 1.0);
    }
    touch_start(integer total_number)
    {
        state drive;
    }
}
state drive
{
    state_entry()
    {
        llSetText("", <1,1,1>, 1.0);
        Count = 0;
        // Ändere den Text hier drunter nach deinen Wünschen. Der kommt nur beim Start der Tour
        // Change the text below as you like. It appears only at the start of the tour
        Say("Willkommen bei der Tour auf meiner Insel. Sie dauert etwa 20 Minuten. Viel Spass :-)");
        SFrame();
    }
    not_at_target()
    {
        if(SFnotat())
        {
            if(DEBUG)
            {
                if(LANGUAGE == 0) llOwnerSay("Wegpunkt Nr. " + (string)(Count + 1) + " bei " + (string)llList2Vector(Points, Count));
                else if(LANGUAGE == 1) llOwnerSay("waypoint no. " + (string)(Count + 1) + " at " + (string)llList2Vector(Points, Count));
            }
            if(llList2String(Text, Count) != "") Say(llList2String(Text, Count));
            if(llList2Float(Pause, Count) > 0) llSleep(llList2Float(Pause, Count));
            Count++;
            if(Count == llGetListLength(Points)) state running;
            SFrame();
        }
    }
}
Tolle Sache,Rebekka.Smile
Geilomat... Oft ruckeln die ja so...
Sorry, ich hätte wohl noch dazusagen sollen dass das Skript so gut wie keinen Lag verursacht, da ja keine Timer oder ähnliches drin sind. Hatte heut mal 20 Schwäne fliegen.. nix nada njet alles beim alten.
Danke Rebekka,
kenne mich leider mit Scripten wenig aus. Könntest Du
bitte mal eine kleines Beispiel-Notecard für die config angeben
wo ich was eintragen soll? Gracias.

Raul
Sicher doch Raul. Hier ist mal der Anfang von meiner config auf meiner Insel.
Code:
DRIVE = <125.996902,118.978127,19.781630> = <0.000000,0.000000,0.095839,0.995397>
DRIVE = <129.360855,120.084579,19.781630> = <0.000000,0.000000,0.438363,0.898798>
Text = Der "Konferenzraum". Zum Sitzen, Plaudern und was Schlürfen
Pause = 5
DRIVE = <131.195618,118.956589,19.781630> = <0.000000,0.000000,-0.043629,0.999048>
DRIVE = <181.989090,112.229759,19.781630> = <0.000000,0.000000,-0.043629,0.999048>
DRIVE = <183.967407,113.936722,19.781630> = <0.000000,0.000000,0.398729,0.917069>
DRIVE = <227.738373,160.869247,19.781630> = <0.000000,0.000000,0.398729,0.917069>
Text = Bitte nicht zu weit rausschwimmen...
DRIVE = <240.843246,207.069016,19.781630> = <0.000000,0.000000,0.601784,0.798659>
DRIVE = <230.657440,215.871841,19.781630> = <0.000000,0.000000,0.953705,0.300744>
Text = Eine kleine Insel zum Entspannen
Pause = 5
DRIVE = <230.556534,215.685242,56.191044> = <0.000000,0.000000,-0.999848,0.017414>
<211.900406,215.035172,56.191044> = <0.000000,0.000000,-0.999848,0.017414>
Text = Eine luftige Tanzfläche für Pärchen mit Slow-Musik
Pause = 5
Vielen Dank Rebekka ! Smile Smile Smile
Als Ergänzung zu dem Routenskript (und auf Wunsch) hab ich noch ein kleines Skript gebastelt, dass selbstständig eine config NC erstellt. Einfach in das Objekt legen (ohne das Routenskript) und anklicken, dann erscheint ein Menü, mit dem ihr die Positionen und Rotation speichern könnt. Bewegt und dreht das Objekt dahin wo es hin soll, dann auf "Position" klicken, evtl. noch eine Pause und/oder ein Text mit dazu und weiter gehts. Seid ihr fertig, wird bei Klick auf "Ende" eine NC erstellt. Dazu muss aber das Threat-Level mindestens High sein. Dann legt ihr das Routenskript hinein, setzt es zurück und fertig.
Viel Spass :-)
Code:
integer Channel = -888888;
integer Listener;
integer Listener1;

list Items;
integer Modus;

Menu()
{
    list l = ["Abbruch", "Ende", "Position", "Pause", "Text"];
    llListenRemove(Listener);
    Listener = llListen(Channel, "", llGetOwner(), "");
    llDialog(llGetOwner(), "Wähle eine Option:", l, Channel);
}

default
{
    state_entry()
    {
        Items = [];
        state running;
    }
}
state running
{
    state_entry()
    {
        Items = [];
    }
    touch_start(integer total_number)
    {
        if(llDetectedKey(0) == llGetOwner()) Menu();
    }
    listen(integer channel, string name, key id, string message)
    {
        if(channel == Channel)
        {
            if(message == "Abbruch")
            {
                Items = [];
                llListenRemove(Listener);
                return;
            } else if(message == "Ende")
            {
                osMakeNotecard("config", Items);
                llSay(0, "Die Notecard wurde erstellt.");
                llRemoveInventory(llGetScriptName());
            } else if(message == "Position")
            {
                string s = "DRIVE = " + (string)llGetPos() + " = " + (string)llGetRot();
                Items += [s];
                llSay(0, "Die Position/Rotation wurde gespeichert.");
                Menu();
                return;
            } else if(message == "Pause")
            {
                Modus = 1;
                llSay(0, "Bitte die Pause in Sekunden im Chat eingeben, z.B. 5.0.");
                Listener1 = llListen(0, "", llGetOwner(), "");
            } else if(message == "Text")
            {
                Modus = 2;
                llSay(0, "Bitte den gewünschten Text im Chat eingeben.");
                Listener1 = llListen(0, "", llGetOwner(), "");
            }
        } else if(channel == 0)
        {
            if(Modus == 1)
            {
                float f = (float)message;
                if(f > 0)
                {
                    Items += ["Pause = " + message];
                    llSay(0, "Pause gespeichert.");
                }
                llListenRemove(Listener1);
                Menu();
                return;
            } else if(Modus == 2)
            {
                message = llStringTrim(message, STRING_TRIM);
                if(message != "")
                {
                    Items += ["Text = " + message];
                    llSay(0, "Text gespeichert.");
                }
                llListenRemove(Listener1);
                Menu();
                return;
            }
        }
    }
}
Hallo Rebekka,
ich habe seit Update auf OS 9.01 ein ungelöstes Problem mit dem Tour - bzw. smooth move Skript.
Da du Dich mit dem Script bereits auseinander gesetzt hast, melde ich mich mal unter Deinem Beitrag.

Nach Update auf die aktuelle OS Version ist ein Thema von mir auf Gridtalk offen:
https://www.gridtalk.de/showthread.php?tid=3291&page=2.

In Kürze die Fehlerbeschreibung: Nach Script Rezzung werden die Wegepunkte eingelesen. Nach touch auf das object, bewegt sich das object richtung start point. Ohne Zutun passiert nichts weiter. Gehe ich auf Bearbeitung des objects und führe eine kleine Bewegung aus, dann läuft das Script weiter zum nächsten way point und stopt erneut (immer so weiter). Fehlermeldungen gibts keine.
Unter älteren OS Versionen ist alles ok.

Gruss
Hallo Cosmic
Vor längerer Zeit hatte ich mal ein ähnliches Problem. Da ich die verschiedenen OS-Versionen nicht kenne, weiss ich auch nicht, woran das liegt. Jedenfalls ist es so, dass die Abbruchbedingung in der Funktion SFnotat nicht mehr richtig ausgewertet wird. Ersetze diese mal durch die folgende, dann sollte es wieder gehen.
LG Rebekka
Code:
integer SFnotat()
{
    if (SF_target== -1) return TRUE;
    float time=llGetTime();
    time = (time-SF_stime)/SF_seconds;
    float f = llVecDist(llGetPos(), SF_epos);
    if(f <= 0.2)
    {
        llOwnerSay("Fertig");
        llTargetRemove(SF_target);
        SF_target=-1;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,SF_epos,PRIM_ROTATION,SF_erot]);
        return TRUE;
    }
    float emit= 1.0-time;
    vector pos=SF_epos*time+SF_spos*emit;
    rotation rot = <
        SF_erot.x*time+SF_srot.x*emit,
        SF_erot.y*time+SF_srot.y*emit,
        SF_erot.z*time+SF_srot.z*emit,
        SF_erot.s*time+SF_srot.s*emit
            >;
    emit = llSqrt(rot.x*rot.x+rot.y*rot.y+rot.z*rot.z+rot.s*rot.s);
    rot = <rot.x/emit,rot.y/emit,rot.z/emit,rot.s/emit>;
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POSITION,pos,PRIM_ROTATION,rot]);
    return FALSE;
}
Seiten: 1 2