This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
NPC SOLOPOSER Script mit Profilinfo, Sim Restartfest
#1
P602 EINZEL NPC Animator mit sequentieller Animations Liste

Eine sinnvoller Einsatz sind Ambiente NPCs die ständig gerezzt sind, und alleine auf der Sim stehen.
Daher ermöglicht der Controller auch eine Steuerung von Ausserhalb des Posers durch berechtigte Avas.


Anwendungebeispiele:
   
- Tänzer
- Tankwart
- Chatbot
- Begrüßungs AVA
- Barkeeper
....


FUNKTIONSUMFANG:

Es wird ein resetfester NPC gerezzt, der auch ein Profilbild und eine ProfilInfo erhält.
Dieser NPC wird per Timer überwacht und bei Verlust neu gerezzt. Somit übersteht er Sim Restarts.

Er wird sequentiell animiert, wobei die Animationsabfolge in einer Liste eingestellt wird.
Jede Animation kann eine eigene zugehörige Dauer haben.
Aber alle Animationen müssen den gleichen Zentralpunk haben, der manuell festgelegt wird.

Die Bedienung erfolgt von aussen duch Click auf den Poser.


FUNKTIONSBESCHREIBUNG:

Das Script dient dazu einen NPC resetfest dauerhaft zu animieren. Es kann aber auch zur Animation eines Avatars verwendet werden.
Die Bedienung erfolgt von einem nicht auf dem Poser sitzenden Avatar aus, oder automatisch.
Dafür gibt es im Script ein Berechtigungs System: Besitzer / Gruppe / AVA per UUID / Jeder.
An Funktionen gibt es Rezzen, Löschen, Animationswechsel.

Nach Scriptreset (z.Bsp: durch Simrestart, Inventaränderung, ...) rezzt es nach einer Wartezeitautomatisch einen NPC sofern der Poser frei ist, und setzt diesen auf den Poser.
Ist der Poser frei, so kann ihn auch ein Avatar nutzen.

Das Script erfordert OSSL Befehl Berechtigung in der Sim.

Der NPC wird im Gruppenkontext des Lands gerezzt, daher braucht die Gruppe Landzugang.
Dafür kann aber sie Sim auch für die Öffentlichkeit gesperrt werden.

Das Script Ermittelt die Anzahl der Animationen (in der Liste) automatisch und Spielt dies sequentiell, in einer Schleife ab.


NOMENKLATUR:
Die NPC Notecard muss mit .NPC anfangen gefolgt von einem Leerzeichen.
Die Syntax ist identisch mit PMAC! Beispiel: ".NPC123 Amanda String"
Der angezeigte NPC Name fängt mit der 9.Stelle an
Das Script unterstützt für den NPC ein Profilfoto und eine Profilinfo.
Für das den Namen des Profilfotos gilt im obigen Beispiel folgende Sytax:  ".bild Amanda String"
Für die Profilbeschreibung muss die Notecard folgenden Namen aufweisen:    ".info Amanda String"

Die Animationssequenz wird in der Liste "aniliste" sequenziell eingetragen.
Zugehörig zu den Animationen muss in der Liste "anidauerliste" die jeweilige Spielzeit pro Animation hinterglegt sein.

Weitere Hinweise finden sich im Script.

Code:
// P602 EINZEL NPC Animator mit sequentieller Animations Liste V1.4       by Tron Mcp       10.2021
// Das Script darf nicht gegen Geld verkauft werden, und muss fullperm bleiben. Der Autor ist als Urheber zu nennen.
// Alle anderen Nutzungen sind erlaubt.
//
// FUNKTIONSUMFANG:
// Es wird ein NPC gerezzt, der auch ein Profilbild und eine ProfilInfo hat.
// Der NPC wird überwacht und bei Verlust neu gerezzt. Somit übersteht er Sim Restarts.
// Er wird sequentiell animiert, und ist von ausserhalb des Posers bedienbar.
//
// FUNKTIONSBESCHREIBUNG:
//
// Das Script dient dazu einen NPC resetfest dauerhaft zu animieren. Es kann aber auch zur Animation eines Avatars verwendet werden.
// Die Bedienung erfolgt von einem nicht auf dem Poser sitzenden Avatar aus, oder automatisch.
// Es ist ein Berechtigungs System enthalten wer den NPC bedienen darf (Rezzen, Löschen, Animationswechsel).
//
// Nach Scriptreset (z.Bsp: durch Simrestart, Inventaränderung, ...) rezzt es einer Wartezeit einen NPC automatisch sofern der Poser frei ist, und setzt diesen auf den Poser.
// mit Klick auf das Prim kann der NPC gelöscht, und mit einem weiteren Klick wieder gerezzt werden.
// Ist der Poser frei, so kann ihn auch ein Avatar nutzen.

// das Script erfordert OSSL Befehl Berechtigung in der Sim.
// Der NPC wird im Gruppenkontext des Lands gerezzt, daher braucht die Gruppe LandZugang.
// Das Script Ermittelt die Anzahl der Animationen (in der Liste) automatisch und Spielt dies sequentiell, in einer Schleife ab.

// die NPC Notecard muss mit .NPC anfangen gefolgt von einem Leerzeichen.
// Die Syntax ist identisch mit PMAC! Beispiel: ".NPC123 Amanda String"
// Der angezeigte NPC Name fängt mit der 9.Stelle an
//
// Das Script unterstützt für den NPC ein Profilfoto und eine Profilinfo.
// für das den Namen des Profilfotos gilt im obigen Beispiel folgende Sytax:  ".bild Amanda String"
// für die Profilbeschreibung muss die Notecard folgenden Namen aufweisen:    ".info Amanda String"

// Die Animationssequenz wird in der Liste "aniliste" sequenziell eingetragen.
// Zugehörig zu den Animationen muss in der Liste "anidauerliste" die jeweilige Spielzeit pro Animation hinterglegt sein.


integer autostart = TRUE;                        // TRUE / FALSE   Soll der NPC automatisch gestartet werden? Bei Scriptreset und Sim Neustartestartet

integer debug = FALSE;                           // Entwickler Infos anzeigen

list    zugangsliste = ["b6a520ac-a468-4bc3-9e52-b509e88a8bce","18da7264-3260-4b63-8173-2a6fd7e93e33","798a6b1e-2186-4cf2-b733-460cb7132ae9"]; // UUIDS berechtigter AVAs
integer groupaccess  = FALSE;                    // TRUE ore FALSE - darf die Gruppe steuern?
integer publicaccess = FALSE;                    // TRUE ore FALSE - darf jeder steuern?
vector  sitzposition = < 0.0, 0.0, 0.8>;         // Sitzposition als Offset zum Prim
vector  schriftfarbe = <0.702, 0.0, 0.0>;        // Farbe des "dance" Primschriftzugs

// Animationsnamen sequentiell auflisten
// Animationsdauer sequentiell auflisten. Zeit 0 eingeben bedeutet Pose endlos abspielen
list     aniliste = ["ani1", "ani2", "ani3"];
list     anidauerliste = [ 15.0 , 30.0 , 60.0   ];

string  sitztext = "Dance!";


////// ab hier Systemvariablen - nichts einzustellen

key     npc = NULL_KEY;         // UUID des gerezzten NPC
key     toucher;                // UUID des Operator
key     dancer;                 // UUID des Posertänzer

string  npc_name;
string  npcnotecard;
integer bereit;
integer animationszahl;
integer aktuellanimation;
string  aktanimation;
integer linkzahl;               // Links leeren Posers.
integer inuse;                  // TRUE wenn Poser in Nutzung ist
integer bot;                    // TRUE wenn User eine BOT ist


osAvatarPlayAnimation(key avatar, string animation)
{
    llStartAnimation(animation);
}


osAvatarStopAnimation(key avatar, string animation)
{
    llStopAnimation(animation);
}


nextanimation(key who)                    // auf nächste Animation einer vorgegeben Sequent wechseln
{
    aktuellanimation++;
    if( aktuellanimation >= animationszahl) { aktuellanimation = 0;}
    osAvatarStopAnimation(who,aktanimation);
    aktanimation = llList2String(aniliste,aktuellanimation);
    float dancetime = llList2Float(anidauerliste,aktuellanimation);
    if(debug) llWhisper(0,"Animation: "+ aktuellanimation + " "+ aktanimation + " Laufzeit: "+ (string)dancetime  );
    osAvatarPlayAnimation(who,aktanimation);
    llSetTimerEvent(dancetime);
}


integer berechtigungscheck(string clicker, integer selbegruppe)  // Zugangsberechtigung auswerten
    {
        integer zugang = FALSE;
        integer personalzugang = llGetListLength(zugangsliste);
        if (publicaccess)  { zugang = TRUE;}                     // Öffentlicher Zugang
        else if (selbegruppe && groupaccess) { zugang = TRUE;}   // Gruppen Zugang
        else if (clicker ==  llGetOwner()) { zugang = TRUE;}     // Besitzer Zugang immer erlaubt
        else if (personalzugang)                                 // Persönlicher Zugang über UUID Liste
        {
            string personal;
            do
            {  
                personal = llList2String(zugangsliste, personalzugang -1 );
                if( clicker ==  personal) { zugang = TRUE; }
                personalzugang--;
            }       
            while ( personal && (!zugang));
        }
        return zugang;
    }


integer lese_nc_name()                                              // NPC Notecard prüfen
{
    integer notecards = llGetInventoryNumber(INVENTORY_NOTECARD);   // Anzahl Notecards ermitteln
    while (notecards)                                               // Test ob Notecard vorhanden
    {
        npcnotecard = llGetInventoryName(INVENTORY_NOTECARD,notecards-1);     // Namen der 1. Notecard ermitteln
        if(debug) llSay (0,(string)npcnotecard);
        if (llSubStringIndex(npcnotecard,".NPC")==0)                // Testen ob sie eine .NPC Notecard ist
        {
            npc_name = llGetSubString(npcnotecard,8,-1);            // npc_namen ermitteln
            if(debug) llSay(0,"NPC Namen: " + npc_name );
            return(TRUE);
        }
        notecards--;
    }
    return(FALSE);
}


key npc_rezzer(key sittarget, vector npcPos)    // NPC im GRUPPENKONTEXT rezzen, damit der auf Sims geht die öffentlich gesperrt, aber für Gruppe frei ist
{
    key npctorez = osNpcCreate(npc_name, "" , npcPos, npcnotecard, 8 | OS_NPC_NOT_OWNED | OS_NPC_SENSE_AS_AGENT | OS_NPC_OBJECT_GROUP );
    osNpcSit(npctorez,sittarget,OS_NPC_SIT_NOW);
    if (llGetInventoryKey(".bild " + npc_name)) osNpcSetProfileImage(npctorez,".bild "+ npc_name);                   // Testen ob Profilbild vorhanden - dann laden
    if (llGetInventoryKey(".info " + npc_name) != (string)NULL_KEY )
    {
        string info = (string) osGetNotecard(".info " + npc_name);
        osNpcSetProfileAbout(npctorez, info);  // Testen ob Profilinfo Notecard vorhanden - dann laden
    }
    bot = TRUE;
    return npctorez;
}


key npc_killer(key npctokill)                    // NPC Löschen
{
    osNpcStand(npctokill);
    llSleep(1.0);
    osNpcRemove(npctokill);
    bot = FALSE;
    return(NULL_KEY);
}   


default
{
    state_entry()
    {
        linkzahl = llGetNumberOfPrims();
        bereit = lese_nc_name();
        if(bereit) { if(autostart) { llSetTimerEvent(30.0); llWhisper(0,"in 30 Sekunden wird ein NPC gerezzt"); }}
        else { llSay(0,"Keine gültige NPC Notecard gefunden"); }
        animationszahl = llGetListLength(aniliste);
        aktuellanimation = -1;
        llSetSitText(sitztext);
        llSetText(sitztext, schriftfarbe, 1.0);
        llSitTarget(sitzposition, ZERO_ROTATION);
    }


    changed (integer change)
    {
        if ( change & ( CHANGED_INVENTORY | CHANGED_REGION_START )) { if(bot) npc = npc_killer(npc); llSleep(1.0); llResetScript();}  // Inventory Änderung und Sim Restart abfangen
       
        if (change & CHANGED_LINK)
        {
            if(linkzahl != llGetNumberOfPrims())                    // mindestens einer hat sich gesetzt
            {
                inuse = TRUE;
                dancer = llGetLinkKey(llGetNumberOfPrims());
                bot = osIsNpc(dancer);
                llSetText(" ", schriftfarbe, 0.0);
                llRequestPermissions(dancer, PERMISSION_TRIGGER_ANIMATION );
                llSleep(1.0);
                aktanimation = "sit";
                nextanimation(dancer);
            }
            else                                                                    // Jemand ist aufgestanden
            {
                inuse = FALSE;
                osAvatarStopAnimation(dancer, aktanimation);
                osAvatarPlayAnimation(dancer, "stand");
                llSetText(sitztext, schriftfarbe, 1.0);
            }
        }
    }
   
   
    touch_start(integer number)                                                     // Prim wurde geklickt
    {   
        toucher = llDetectedKey(0);
        integer gruppe = llDetectedGroup(0);
        integer access = berechtigungscheck(toucher,gruppe);                        // Berechtigung checken
       
        if(access)
        {
            if (!inuse) {npc = npc_rezzer( llGetKey(), llGetPos());}                // Poser frei -> NPC rezzen
            else if (inuse & bot) {npc = npc_killer(npc); llSetTimerEvent(0);}        // Poser mit NPC besetzt -> NPC löschen
            else if (inuse & !bot) {nextanimation(dancer);}                // Poser mit Ava besetzt -> nächster Tanz
        }
    }
   
   
    timer()
    {
        if(!inuse) {npc = npc_rezzer( llGetKey(), llGetPos());}                    // wenn Poser leer, NPC rezzen
        else nextanimation(dancer);                                                    // wenn Poser besetzt, nächsten Tanz wählen
    }
}


Viel Spaß

Tron
The following 4 users say Thank You to Tron Mcp for this post:
  • Coffeetime (09-21-2022), Jupiter Rowland (09-22-2022), Lukas (09-20-2022), Maria Silberstein (09-20-2022)
Zitieren


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste