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.

Hallo, Gast
Sie müssen sich registrieren bevor Sie auf unserer Seite Beiträge schreiben können.

Benutzername
  

Passwort
  





Durchsuche Foren

(Erweiterte Suche)

Foren-Statistiken
» Mitglieder: 23
» Neuestes Mitglied: Lilida
» Foren-Themen: 599
» Foren-Beiträge: 1.567

Komplettstatistiken

Aktive Themen
Red light district
Forum: Informationen und aktuelle Meldungen
Letzter Beitrag: Cheryl Furse
Vor 2 Stunden
» Antworten: 3
» Ansichten: 69
Tanzball rezzen
Forum: OpenSim-Manager
Letzter Beitrag: Lilida
16.04.2024, 14:27
» Antworten: 6
» Ansichten: 476
Was ist ne Kaffestube ohn...
Forum: Kaffeestube
Letzter Beitrag: Susan
15.04.2024, 15:17
» Antworten: 0
» Ansichten: 197
Sim geht in Schlafmodus
Forum: OpenSim
Letzter Beitrag: Scarlett Candor
11.04.2024, 10:16
» Antworten: 3
» Ansichten: 437
C Programmierung und bull...
Forum: Scripting
Letzter Beitrag: Cheryl Furse
07.04.2024, 00:50
» Antworten: 2
» Ansichten: 298
Steampunk-Party mit Marlo...
Forum: Informationen und aktuelle Meldungen
Letzter Beitrag: ThunderTower
02.04.2024, 18:29
» Antworten: 0
» Ansichten: 232
ERÖFFNUNG FLORES SEA Wild...
Forum: Informationen und aktuelle Meldungen
Letzter Beitrag: ThunderTower
01.04.2024, 18:52
» Antworten: 3
» Ansichten: 313
Einladung zur SCIFI Party...
Forum: Virtual Africa
Letzter Beitrag: Cheryl Furse
31.03.2024, 13:32
» Antworten: 7
» Ansichten: 627
Das Ei ist hart
Forum: Kaffeestube
Letzter Beitrag: ThunderTower
30.03.2024, 16:38
» Antworten: 0
» Ansichten: 245
Lukas, melde dich bitte, ...
Forum: Kaffeestube
Letzter Beitrag: Tron Mcp
25.03.2024, 12:31
» Antworten: 2
» Ansichten: 305

 
  PMAC POSER V2.8 BASISSCRIPT TEIL1
Geschrieben von: Tron Mcp - 15.02.2024, 10:55 - Forum: Animieren - Keine Antworten

PMAC POSER V2.8 BASISSCRIPT TEIL1


Dieser Artikel enthält meine Weiterentwicklung des PMAC Posers. Ein Fork der Version 2.0

Das Script kann direkt in vorhandenen alten PMAC Poser bis 2.2 zum Austausch verwendet werden.

Was sind die Haupt Änderungen?

NPCs: NPC Rezzt nun im Gruppenkontext des Prims - damit NPCS auch auf Sims mit ausschließlich Gruppenzugang funktionieren.
Somit können NPCs auch auf gesperrten Sims eingesetzt werden, und fliegen auch nicht heraus wenn man später die Sim sperrt.

NPCs: Unterstützung für NPC Profil Foto. Fotos müssen ".bild npcname" heissen damit sie als Profilfoto im NPC Profil geladen werden.
Beispiel: die NPC Notecard heisst: ".NPC192 Donna Orphelia" so muss das Profilfoto ".bild Donna Ophelia" benannt werden.

NPCs: Unterstützung für NPC Profil Info. Notecard muss ".info npcname" heissen, damit deren Inhalt im Info Feld des Profils angezeigt wird.
Beispiel: die NPC Notecard heisst: ".NPC192 Donna Orphelia" so muss die Profilinfo ".info Donna Ophelia" benannt werden.
Die Notizkarte dafür erstellt man inworld. Leider ist die Textlänge im Simulator sehr beschränkt. Der Inhalt der Notizkare wird dann im Profil Info Textfeld dargestellt.

Menü Rechte Änderung: NPC Tänzer können nun von jedem Nutzer geholt werden
Es besteht nun die Möglichkeit vorzugeben wer auf dem Poser Rechte hat Posereigene NPCs zu laden oder zu löschen.
dafür werden folgende Variablen verwendet:
publicaccess   { zugang = TRUE;}                    Öffentlicher Zugang
groupaccess   { zugang = TRUE;}                    Gruppen Zugang
zugangsliste                                                      Persönlicher Zugang über UUID Liste
der Poserbesitzer hat immer Zugang
Ihr findet die Einstellmöglichkeit im Script:
list    zugangsliste = ["b6a520ac-a468-4bc3-9e52-b509e88a8bce","18da7264-3260-4b63-8173-2a6fd7e93e33","798a6b1e-2186-4cf2-b733-460cb7132ae9"]; // UUIDS berechtigter AVAs
integer groupaccess = FALSE;  // TRUE/FALSE - darf die Gruppe steuern?
integer publicaccess = FALSE; // TRUE/FALSE - darf jeder steuern?

Admin Rechtestruktur erweitert vom Owner auf Berechtigte

SIMCROSSING Fähigkeit: Script Reset bei Simwechsel und Region Neustart ist nun wählbar um Simcrossing Fahrzeuge mit PMAC zu ermöglichen. (Bug in Opensim kompensieren)

Gender detection von AVA,NPC und Animationen (letzter Animationsbuchstaben F f oder M m) sowie Posen Zuordnung beim Hinsetzten

ES GIBT NOCH MEHR NEUE FUNKTIONEN, ABER DIE BESCHREIBEN ICH SPÄTER IN EINEM ANDEREN ARTIKEL

Ihr müsst es aber in 2 Teilen herunterladen und im Script Editor zu einem Script zusammen setzen.
Der Code ist zu lang für einen Artikel des Forums. Dieses ist NUR der 1. Teil!
Als eindeutige Beschriftung empfehle ich: P607 PMAC 2.8 Poser UNIVERSAL + NPC 122022.lsl

TEIL1:    "P607 PMAC 2.8 Poser UNIVERSAL + NPC 122022.lsl"

Code:
// P607 PARAMOUR MULTI-ANIMATION CONTROLLER (PMAC) v2.8-NPC Universal VERSION
// by Aine Caoimhe (Mata Hari)(c. LACM) March 2015-February 2016
// Provided under Creative Commons Attribution-Non-Commercial-ShareAlike 4.0 International license.
// Please be sure you read and adhere to the terms of this license: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// *** THIS SCRIPT REQUIRES (AND WILL ONLY WORK) IN REGIONS WHERE THE SCRIPT OWNER HAS OSSL FUNCTION PERMISSIONS ***
// *** THIS SCRIPT MUST ALWAYS BE LOCATED IN THE ROOT PRIM OF A LINKSET ***
// NPCs: NPC Rezzt nun im Gruppenkontext des Prims - damit NPCS auch auf Sims mit ausschließlich Gruppenzugang funktionieren.
// NPCs: Unterstützung für NPC Profil Foto. Fotos müssen ".bild npcname" heissen damit sie als Profilfoto im NPC Profil geladen werden.
// NPCs: Unterstützung für NPC Profil Info. Notecard muss ".info npcname" heissen, damit deren Inhalt im Info Feld des Profils angezeigt wird.
// Menü Rechte Änderung: NPC Tänzer können nun von jedem Nutzer geholt werden
// Admin Rechtestruktur erweitert vom Owner auf Berechtigte
// SIMCROSSING Fähigkeit: Script Reset bei Simwechsel und Region Neustart ist nun wählbar um Simcrossing Fahrzeuge mit PMAC zu ermöglichen. (Bug in Opensim kompensieren)
// Gender detection von AVA,NPC und Animationen (letzter Animationsbuchstaben F f oder M m) sowie Posen Zuordnung beim Hinsetzten
// *********************************************************
// *****  GENERAL USER SETTINGS - ADJUST AS PREFERED   *****
// *********************************************************
string  defaultGroup="Hexdance";    // name of a group (not the full card name!) to load by default regardless of its permission setting
integer resetOnQuit=FALSE;          // TRUE = when no more sitters, reset the script (will also load default group again)
                                    // FALSE = leave most recently loaded animation active
integer ownerUseReq=FALSE;          // TRUE = the owner must be the first to sit and other people can only sit while the owner is still present and seated
                                    // FALSE = no restriction...anyone can sit and use it at any time
integer ownerOnlyMenus=FALSE;       // TRUE = only the owner can access the dialog menus (can be turned off in options menu until script is reset or it is turned on again) - NOT RECOMMENDED unless ownerUseReq=TRUE
                                    // FALSE = anyone can be the controller
integer ownerUseUnlocksPerms=TRUE;  // TRUE = if owner is a current user, all users then have access to all groups and NPCs
                                    // FALSE = only the owner can ever load an owner-only Group or NPC
integer autoOn=TRUE;                // TRUE = will start in auto mode after a reset
                                    // FALSE = will start in manual mode after a reset -- after use will remain in whatever state it was left in unless resetOnQuit=TRUE
float   autoTimer=120.0;            // default time to use for the autotimer (in seconds) - after use will remain at whatever timer was last set to unless resetOnQuit=TRUE;
string  gs_ConfigName=".PMAC-CONFIG"; // Name of optional notecard with user defined configuration that overide the above values if present
integer showGroupsMenuFirst=FALSE;  // TRUE = when first initiating dialog, show the groups menu instead of the current group's animation menu; FALSE = show current group's animation menu
integer allowSoloNPC=TRUE;          // TRUE = NPCs can be left rezzed even if there are no avatars seated; FALSE = kill all NPCs if there are no remaining avatars
integer ownerOnlyRemote=TRUE;       // TRUE = remote commands will only be accepted from scripted objects belonging to the same owner as the PMAC system  (*** NEW IN PMAC 2.0***)
                                    // FALSE = anyone with authority to send osMessageObject() can send a command to PMAC
integer silent=TRUE;                // TRUE = PMAC will only say critical information to chat...usually only errors will be seen (*** NEW IN PMAC 2,0***)
                                    // FALSE = PMAC will notify users of some changes
integer resetOnSimcross= FALSE;     // TRUE/FALSE = restart script on Sim Restart and Simcrossing
// ***************************************
// *****  ADVANCED/BUILDER SETTINGS  *****
// ***************************************
string handleName="~~~positioner";    // inventory object to rez as a handle for positioning
list handleColours=[<1.000, 0.004, 0.667>,<0.004, 0.667, 1.000>,<0.667, 1.000, 0.004>,   // supply as many as you like but ideally at least as many as the expected positions in most of your menus
                    <1.000, 0.004, 0.004>,<0.004, 0.004, 1.000>,<1.000, 0.667, 0.004>,
                    <0.667, 0.004, 1.000>,<0.004, 1.000, 0.667>,<0.004, 1.000, 0.004>];
vector handleSize=<0.2,0.2,3.0>;    // size of handles used in edit mode
float handleAlpha=0.5;                // alpha of handles used in edit mode
string baseAn="~~~~~base_DO_NOT_DELETE_ME!!!!!";    // name of the P1 animation to use for synch
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// * * *  DO NOT CHANGE ANYTHING BELOW HERE UNLESS YOU KNOW WHAT YOU'RE DOING! * * *
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
key user;
list positions;
list invNpc; // fullName | A/G/O | buttonName
integer invNpcStride=3;
list npcList;
integer npcPage;
list invGroups; // fullName | positions | A/G/O | buttonName
integer invGroupStride=4;
list groupList;
integer groupPage;
integer myChannel;
integer diaHandle;
string menu;
string txtDia;
list butDia;
string currentGroup;
list anData; // anName | command | A1Name | A1 Pos | A1 Rot |
integer anStride;
list anList;
list currentAn; // groupName | anName | command | A1Name | A1 Pos | A1 Rot |
integer anPage;
list editHandles;
integer rezzingHandles;
float editTimer=0.2;
string myState="INITIALIZING";
list specials; //buttonName | stringToSend
integer specPage;
integer gi_HaveConfig=0;
// NC_PROP ADDON
integer gi_NC_PROP_CHANGED=FALSE;   // global integer flag to indicate if new prop values have been sent form NC_PROPS addon
string gs_NC_PROP_DATA="";          // global string containing changed props data


key     toucher; // UUID des Operators
list    zugangsliste = ["b6a520ac-a468-4bc3-9e52-b509e88a8bce","18da7264-3260-4b63-8173-2a6fd7e93e33","798a6b1e-2186-4cf2-b733-460cb7132ae9"]; // UUIDS berechtigter AVAs
integer groupaccess = FALSE;  // TRUE/FALSE - darf die Gruppe steuern?
integer publicaccess = FALSE; // TRUE/FALSE - darf jeder steuern?
integer groupusercount;       // Anzahl der zulässigen User in die ser Posergruppe
list    anigenderlist = [];   // Speichert gender pro Animation

// *** ERMITTLUNG DES AVA/NPC GESCHLECHTS
integer GenderDetect(key id)
{
    string geschlecht =  osGetGender(id);
    if ( geschlecht == "female") return 1;
    else if  ( geschlecht == "male") return -1;
    else return 0;
}

// *** GESCHLECHTSSPEZIFISCHES POSITIONIEREN von AVAs und NPCs auf Animationen.
PositioniereAva( integer aktuellerplatz, key wer)
{
    integer usergeschlecht = GenderDetect(wer); // Geschlecht des aktuell zu platzierenden Users ermitteln
    integer anis = llGetListLength(anigenderlist);
    integer lauf = 0;
    integer angender = (integer) llList2String(anigenderlist,aktuellerplatz);  // Geschlecht der aktuelle Pose lesen
    if (usergeschlecht == angender) return; // ich sitze schon richtig   
    do
    {
       key nutzer = llList2String(positions,lauf);
       if(nutzer == NULL_KEY)
       {
            angender = (integer) llList2String(anigenderlist,lauf);
            if (angender == usergeschlecht) // Treffer, ich wechsel auf diese Position
            {
                SwapAvaPositions(aktuellerplatz,lauf);
                aktuellerplatz = lauf;
                return;
             }
       }
       lauf++;
    } while (lauf < anis);
}


// *** ZUGANGSBERECHTIGUNGEN AUSWERTEN
integer BerechtigungsCheck(string clicker, integer selbegruppe)
{
    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;
}

// *** PMAC FENBEDIENUNG
handleRemoteCall(string message)
{
    list call=llParseString2List(message,["|"],[]);
    string command=llList2String(call,0);
    if (command=="PMAC_REMOTE_QUIT")
    {
        if (myState=="RUNNING") QuitEditMode();
        else if (command=="PMAC_REMOTE_SYNCH")
        {
            if (myState=="RUNNING") SyncAvas();
        }
        else
        {
            user=NULL_KEY;
            if (command=="PMAC_REMOTE_AUTO_OFF")
            {
                autoOn=FALSE;
                llSensorRemove();
            }
            else if (command=="PMAC_REMOTE_AUTO_ON")
            {
                autoOn=TRUE;
                float setTime=llList2Float(call,1);
                if (setTime>0.0) autoTimer=setTime;
                else updateAutoTimer(); // check anim to see if custom
                if (myState=="RUNNING") llSensorRepeat("THIS_WILL_NEVER_RETURN_A_SENSOR_RESULT",NULL_KEY,AGENT,0.001,0.0,autoTimer);
            }
            else if ((command=="PMAC_REMOTE_SWAP") && (myState=="RUNNING"))
            {
                integer p1=llList2Integer(call,1);
                integer p2=llList2Integer(call,2);
                if ((p1>=llGetListLength(positions))||(p2>=llGetListLength(positions))) llOwnerSay("ERROR: remote swap calling for a position index that is out of range. There are only "+(string)llGetListLength(positions)+" and you called for "+(string)p1+" and "+(string)p2+". Did you perhaps forget that indexing begins at position 0, not positions 1?");
                else SwapAvaPositions(p1,p2);
            }
            else if ((command=="PMAC_REMOTE_UNSIT") && (myState=="RUNNING"))
            {
                key keyToUnsit=llList2Key(positions,llList2Integer(call,1));
                if (keyToUnsit!=NULL_KEY) llUnSit(keyToUnsit);
            }
            else if ((command=="PMAC_REMOTE_SET_GROUP")||(command=="PMAC_REMOTE_SET_ANIMATION"))
            {
                string newGroup=llList2String(call,1);
                if (llListFindList(invGroups,[newGroup])==-1)
                {
                    llOwnerSay("ERROR! Remote call to load group \""+newGroup+"\" but this group doesn't exist. Please check the name and remember not to include the .menuxxxx prefix portion");
                    return;
                }
                loadAnimGroup(newGroup);
                if (command=="PMAC_REMOTE_SET_ANIMATION")
                {
                    string anToPlay=llList2String(call,2);
                    if (llListFindList(anList,[anToPlay])==-1)
                    {
                        llSay(0,"ERROR! A remote call was received to play animation \""+anToPlay+"\" from group \""+newGroup+"\" but that animation cannot be found. This is a fatal error and requires the system to quit and be reset. You may need to notify the owner and ask them to reset it if it isn't configured to do so automatically on quit.");
                        myState="ERROR";
                        QuitEditMode();
                    }
                    else playAnimation(anToPlay);
                }
            }
        }
    }
}

// *** ANIMATIONS AUSWAHL MENÜ ZEIGEN
showAnMenu()
{
    integer maxAn=llGetListLength(anList);
    integer showStart=(anPage+1);
    integer showEnd=(anPage+6);
    if (showEnd>maxAn) showEnd=maxAn;
    txtDia=""+"ANIMATION MENU: Select an animation\n"+currentlyPlaying()+"\nShowing animation";
    if (showEnd!=showStart) txtDia+="s "+(string)showStart+" to "+(string)showEnd;
    else txtDia+=" "+(string)showStart;
    txtDia+=" of "+(string)maxAn+ " total animations in this group\n\n"+llDumpList2String(llList2List(anList,anPage,anPage+5),"\n");
    butDia=[]+llList2List(anList,anPage,anPage+5);
    while (llGetListLength(butDia)<6) { butDia=[]+butDia+["-"]; }
    butDia=[]+butDia+["< PREV","ADD NPC","SYNCH","NEXT >","GROUPS","OPTIONS","QUIT"];
    menu="MENU_ANIM";
    startListening();
}

// *** ANIMATIONS GRUPPEN MENÜ ZEIGEN
showGroupsMenu()
{
    txtDia=""+"GROUPS MENU: Select a group of animations\n"+currentlyPlaying()+"\nShowing groups "+(string)(groupPage+1)+" to "+(string)(groupPage+6)+" of "+(string)llGetListLength(groupList)+ " total groups\n\n"+llDumpList2String(llList2List(groupList,groupPage,groupPage+5),"\n");
    butDia=[]+llList2List(groupList,groupPage,groupPage+5);
    while (llGetListLength(butDia)<6) { butDia=[]+butDia+["-"];}
    butDia=[]+butDia+["< PREV","SYNCH","NEXT >","<< BACK","OPTIONS","QUIT"];
    menu="MENU_GROUPS";
    startListening();
}

// *** EDIT MENÜ ZEIGEN
showEditMenu()
{
    txtDia=""+"EDIT MODE ACTIVE!!!\n"+currentlyPlaying()+" (#"+(string)(llListFindList(anList,[llList2String(currentAn,1)])+1)+" of "+(string)llGetListLength(anList)+")\n\nPlease ensure you have read and are familiar with the PMAC instructions for using the edit menu, particularly if you use add-on modules. You have been warned...";
    butDia=[]+["< PREV","SYNCH","NEXT >","REVERT THIS","STORE THIS","STORE ADDON","EDIT OFF","SAVE CARD","SAVE NEW"];
    menu="MENU_EDIT";
    startListening();
}

// *** OPTIONEN MENÜ ZEIGEN
showOptionsMenu()
{
    txtDia=""+"OPTIONS MENU:\n\n";
    butDia=[];
    if (user==llGetOwner())
    {
        if (ownerOnlyMenus)
        {
            txtDia+="EDIT ON enters edit mode (all positions must be filled)\nMENUS UNLOCK allows other users to take control\n";
            butDia=[]+butDia+["EDIT ON","MENUS UNLOCK","-"];
        }
        else
        {
            txtDia+="EDIT ON enters edit mode (all positions must be filled)\nMENUS LOCK prevents other users from taking control\n";
            butDia=[]+butDia+["EDIT ON","MENUS LOCK","-"];
        }
    }
    txtDia+="AUTO is used to enable, disable or adjust auto mode\n";
    butDia=[]+butDia+["AUTO","-"];
    if (llGetListLength(specials)>0)
    {
        txtDia+="SPECIAL access special add-on menus\n";
        butDia=[]+butDia+["SPECIAL"];
    }
    else butDia=[]+butDia+["-"];
    txtDia+="SWAP to swap positions\nUNSIT to force someone to stand up or remove a npc\n";
    butDia=[]+butDia+["SWAP","UNSIT"];
    if (llListFindList(positions,[NULL_KEY])>-1)
    {
        txtDia+="ADD NPC to have a NPC join you\n";   // ADD NPC Auswahl
        butDia=[]+butDia+["ADD NPC"];
    }
    else butDia=[]+butDia+["-"];
    butDia=[]+butDia+["<< BACK","SYNCH","QUIT"];
    menu="MENU_OPTIONS";
    startListening();
}

// *** SPECIALS MENÜ ZEIGEN
showSpecialsMenu()
{
    txtDia=""+"SPECIALS MENU\n\nThese are options supplied by any add-ons you have installed. Please consult their instructions for details.\n";
    butDia=[];
    integer i=specPage;
    while (llGetListLength(butDia)<9)
    {
        if (i<llGetListLength(specials))
        {
            butDia=[]+butDia+llList2String(specials,i);
            txtDia+="\n"+llList2String(specials,i);
            i+=2;
        } else butDia=[]+butDia+["-"];
    }
    butDia=[]+butDia+["< PREV","CANCEL","NEXT >"];
    menu="MENU_SPECIALS";
    startListening();
}

// *** AUTO MENÜ ZEIGEN
showAutoMenu()
{
    txtDia="AUTO MENU\n\nAuto mode is currently ";
    butDia=[]+["120","300","600","30","60","90"];
    if (autoOn)
    {
        txtDia+="ON and set to "+(string)llRound(autoTimer)+" seconds\n\nSelect a different time if you wish, or AUTO OFF to switch to manual mode";
        butDia=[]+butDia+["AUTO OFF","-","CANCEL"];
    }
    else
    {
        txtDia+="OFF\n\nSelect AUTO ON to use the last preset time or pick your preferred timer";
        butDia=[]+butDia+["AUTO ON","-","CANCEL"];
    }
    menu="MENU_SELECT_AUTO_MODE";
    startListening();
}

// *** ADD NPC MENÜ ZEIGEN
showAddNpcMenu()
{
    txtDia=""+"ADD NPC\n\nSelect the NPC to add. It will occupy the first available position\n\n"+llDumpList2String(llList2List(npcList,npcPage,npcPage+8),"\n");
    butDia=[]+llList2List(npcList,npcPage,npcPage+8);
    while (llGetListLength(butDia)<9) { butDia=[]+butDia+["-"]; }
    butDia=[]+butDia+["< PREV","CANCEL","NEXT >"];
    menu="MENU_ADD_NPC";
    startListening();
}

// *** GESPIELTE ANIMATION WECHSELN
playAnimation(string name)
{
    if (autoOn) llSensorRemove();
    integer i=llGetListLength(positions);
    while (--i>=0) { if (llList2Key(positions,i)!=NULL_KEY) osAvatarStopAnimation(llList2Key(positions,i),llList2String(currentAn,3+i*3));}
    integer indexAn=llListFindList(anData,[name]);
    list nextAn=[currentGroup]+llList2List(anData,indexAn,indexAn+anStride-1);
   
// Liste erstellen
    anigenderlist = [];
    integer nextanlaenge = llGetListLength(nextAn)/3;
    integer laufvar = 1;
    while (laufvar < nextanlaenge)
    {
        string animname = llList2String(nextAn,laufvar*3);
        integer laenge = llStringLength(animname);
        string buchstabe = llGetSubString(animname,laenge-1,-1);
        buchstabe = llToUpper(buchstabe);
        integer geschlecht = 0;
        if (buchstabe == "F") geschlecht = 1;
        else if (buchstabe == "M") geschlecht = -1;
        anigenderlist = anigenderlist + geschlecht;
        laufvar++;
    }
    integer have=llGetListLength(positions);
    integer need=llRound(((float)llGetListLength(nextAn)-3.0)/3.0);   
    while(have<need) { positions=[]+positions+[NULL_KEY];have++;}
    while ((have>need) && (llListFindList(positions,[NULL_KEY])>=0)) { positions=[]+llDeleteSubList(positions,llListFindList(positions,[NULL_KEY]),llListFindList(positions,[NULL_KEY]));have--;}
    if (have>need)
    {
        llSay(0,"There are currently too many users seated. You will need to reduce the number of seated users by "+(string)(have-need)+" to play it, or select a different group of animations");
        return;
    }
    i=llGetListLength(positions);
    while (--i>=0)
    {
        key who=llList2Key(positions,i);
        if (who!=NULL_KEY)
        {
            osAvatarPlayAnimation(who,llList2String(nextAn,3+i*3));
            setPosition(who,getUserLink(who),llList2Vector(nextAn,4+i*3),llList2Rot(nextAn,5+i*3));
            if (myState=="EDIT") setHandle(llList2Key(editHandles,i),llList2Vector(nextAn,4+i*3),llList2Rot(nextAn,5+i*3));
        }
    }
    currentAn=[]+nextAn;
    llMessageLinked(LINK_THIS,0,"GLOBAL_NEXT_AN|"+llList2String(currentAn,2),llDumpList2String(positions,"|"));
    if (autoOn)
    {
        updateAutoTimer();
        if (myState=="RUNNING") llSensorRepeat("THIS_WILL_NEVER_RETURN_A_SENSOR_RESULT",NULL_KEY,AGENT,0.001,0.0,autoTimer);
    }
}

updateAutoTimer()
{
    list comBlock=llParseString2List(llList2String(currentAn,2),["{","}"],[]);
    integer autoSet=llListFindList(comBlock,["PMAC_SET_AUTO"]);
    if (autoSet>=0)
    {
        if (llList2Float(comBlock,autoSet+1)>0.0) autoTimer=llList2Float(comBlock,autoSet+1);
        else llOwnerSay("ERROR: the animation \""+llList2String(currentAn,1)+"\" is calling for the auto timer to be set to "+llList2String(comBlock,autoSet+1)+". Value supplied must be a non-zero float. Using the previous timer value instead.");
    }
}

// *** AVATARPOSTITION MIT ANDEREN AVAS SYNCHRONISIEREN
SyncAvas()
{
    integer i=llGetListLength(positions);
    while (--i>=0)
    {
        key who=llList2Key(positions,i);
        if (who!=NULL_KEY) {
            osAvatarStopAnimation(who,llList2String(currentAn,3+i*3));
            osAvatarPlayAnimation(who,llList2String(currentAn,3+i*3));
        }
    }
    llMessageLinked(LINK_THIS,0,"GLOBAL_ANIMATION_SYNCH_CALLED",llDumpList2String(positions,"|"));
}

// *** AVATARPOSTITION UNTEREINANDER TAUSCHEN
SwapAvaPositions(integer indFrom,integer indTo)
{
    key whoFrom=llList2Key(positions,indFrom);
    if (whoFrom!=NULL_KEY)
    {
        osAvatarStopAnimation(whoFrom,llList2String(currentAn,3+indFrom*3));
        setPosition(whoFrom,getUserLink(whoFrom),llList2Vector(currentAn,4+indTo*3),llList2Rot(currentAn,5+indTo*3));
    }
    key whoTo=llList2Key(positions,indTo);
    if (whoTo!=NULL_KEY)
    {
        osAvatarStopAnimation(whoTo,llList2String(currentAn,3+indTo*3));
        setPosition(whoTo,getUserLink(whoTo),llList2Vector(currentAn,4+indFrom*3),llList2Rot(currentAn,5+indFrom*3));
    }
    positions=[]+llListReplaceList(positions,[whoFrom],indTo,indTo);
    positions=[]+llListReplaceList(positions,[whoTo],indFrom,indFrom);
    SyncAvas();
}

// *** MENÜKONTROLLE DURCH ANDEREN AVA ÜBERNEHMEN
ChangeMenuUser(key who)
{
    if ((user!=NULL_KEY)&&!silent) llRegionSayTo(user,0,llGetUsername(who)+" has now taken control of me");
    user=who;
    buildGroupList();
    specials=[];
    llMessageLinked(LINK_THIS,0,"GLOBAL_NEW_USER_ASSUMED_CONTROL|"+(string)user,llDumpList2String(positions,"|"));
    if (llListFindList(groupList,[currentGroup])==-1) loadAnimGroup(llList2String(groupList,0));
    else if (autoOn) showGroupsMenu();
    else if (showGroupsMenuFirst) showGroupsMenu();
    else showAnMenu();
}

// *** EDITMODUS VERLASSEN
QuitEditMode()
{
    if (myState=="EDIT") removeHandles();
    integer i=llGetListLength(positions);
    while (--i>=0)
    {
        key who=llList2Key(positions,i);
        if (who!=NULL_KEY)
        {
            if (osIsNpc(who)) osNpcRemove(who);
            else
            {
                if (!silent) llRegionSayTo(who,0,"Quit called");
                llUnSit(who);
            }
        }
    }
}

// *** NEUE ANIMATIONSGRUPPE LADEN
loadAnimGroup(string name)
{
    if (name==currentGroup) { if(user!=NULL_KEY) showAnMenu(); return;}
    integer indToLoad=llListFindList(invGroups,[name])-3;
    groupusercount=llList2Integer(invGroups,indToLoad+1);  // Zugelassene Userzahl in der Animations Gruppe
    if (groupusercount<llGetListLength(positions))  // Gruppe enthält zu wenige Animationen für sitzende User
    {
        integer agents;
        integer a=llGetListLength(positions);
        while (--a>-1) { if (llList2Key(positions,a)!=NULL_KEY) agents++;}
        if (agents>groupusercount)
        {
            llRegionSayTo(user,0,"You cannot use animations from the "+name+" group at the moment because it is for a maximum of "+(string)groupusercount+" users and there are currently "+(string)agents+" seated. Please select a different group of animations, remove NPCs, or ask someone to stand.");
            if (user!=NULL_KEY) startListening();
            return;
        }
    }
    currentGroup=name;      // Erfolgreich auf neue Animations Gruppe geschalten
    anData=[]+llParseString2List(osGetNotecard(llList2String(invGroups,indToLoad)),["|","\n"],[""]);
    anStride=2+(3*groupusercount);
    anPage=0;
    anList=llList2ListStrided(anData,0,-1,anStride); // Animationsliste füllen
    if (autoOn && (myState=="RUNNING"))
    {
        playAnimation(llList2String(anList,0));
        if (user!=NULL_KEY)
        {
            if (!silent) llRegionSayTo(user,0,"Now automatically playing animations from "+name);
            showGroupsMenu();
        }
    } else if (user!=NULL_KEY) showAnMenu();
}

// *** PMAC KONFIGURATIONSPARAMETER LADEN
loadConfig()
{
    integer i;
    float n;
    string  sParam;
    string  sValue;
    list lParams=[];
    for(i=0;i<osGetNumberOfNotecardLines(gs_ConfigName); i++)
    {
        lParams=llParseString2List(osGetNotecardLine(gs_ConfigName,i),["="],"");
        if (llGetListLength(lParams)==2)
        {
            sParam=llStringTrim(llList2String(lParams,0),STRING_TRIM);
            sValue=llStringTrim(llList2String(lParams,1),STRING_TRIM);
            if ((sParam=="defaultGroup") || (sParam=="DefaultGroup")) { defaultGroup=sValue; }
            else if ((sParam=="resetOnQuit")||(sParam=="ResetOnQuit")) { resetOnQuit=(sValue=="TRUE");}
            else if ((sParam=="ownerUseReq")||(sParam=="OwnerUseReq")) { ownerUseReq=(sValue=="TRUE");}
            else if ((sParam=="ownerOnlyMenus")||(sParam=="OwnerOnlyMenus")) { ownerOnlyMenus=(sValue=="TRUE");}
            else if ((sParam=="ownerUseUnlocksPerms")||(sParam=="OwnerUseUnlockPerms")) { ownerUseUnlocksPerms=(sValue=="TRUE");}
            else if ((sParam=="autoOn")||(sParam=="AutoOn")) { autoOn=(sValue=="TRUE");}
            else if ((sParam=="autoTimer")||(sParam=="AutoTimerValue")) { autoTimer=(float)sValue;}
            else if ((sParam=="baseAn")||(sParam=="BaseAnimation"))    { baseAn=sValue;}
            else if ((sParam=="showGroupsMenuFirst")||(sParam=="ShowGroupsMenuFirst")) { showGroupsMenuFirst=(sValue=="TRUE");}
            else if ((sParam=="allowSoloNPC")||(sParam=="AllowSoloNPC")) { allowSoloNPC=(sValue=="TRUE");}
            else if ((sParam=="ownerOnlyRemote")||(sParam=="OwnerOnlyRemote")) { ownerOnlyRemote=(sValue=="TRUE");}
            else if ((sParam=="silent")||(sParam=="Silent")) { silent=(sValue=="TRUE");}
            else { llOwnerSay("Warn: Unable to parse user defined configuration "+llDumpList2String(lParams,"="));}
        }
        else if (llGetListLength(lParams)!=0) { llOwnerSay("Warn: Skipping user defined configuration line "+(string)i+"  "+llDumpList2String(lParams,"="));}
    }
}

// *** ANIMTIONS GRUPPEN LISTE ERSTELLEN
buildGroupList()
{
    groupList=[];
    groupPage=0;
    integer i;
    while (i<llGetListLength(invGroups))
    {
        if ( ( llList2String(invGroups,i+2)=="A" ) || ( (llList2String(invGroups,i+2)=="G") && llSameGroup(user)) || (user==llGetOwner()) ||  (llListFindList(positions,[llGetOwner()])>=0)  ) groupList=[]+groupList+[llList2String(invGroups,i+3)];
        i+=invGroupStride;
    }
}

// *** LISTE VERFÜGBARER NPCS ERSTELLEN für Menüauswahl
buildNpcList()
{
    npcList=[];
    npcPage=0;
    integer i;
    while (i<llGetListLength(invNpc))
    {// NPCs darf nun jeder laden
        npcList=[]+npcList+[llList2String(invNpc,i+2)];
        i+=invNpcStride;
    }
    showAddNpcMenu();
}

// *** INVENTAR AUSWERTEN
buildInventoryLists()
{
    invGroups=[];
    invNpc=[];
    integer i=llGetInventoryNumber(INVENTORY_NOTECARD);
    while (--i>-1)
    {
        string name=llGetInventoryName(INVENTORY_NOTECARD,i);
        if (llSubStringIndex(name,".menu")==0)
        {
            integer nameStarts=llSubStringIndex(name," ")+1;
            if (llListFindList(invGroups,[llGetSubString(name,nameStarts,-1)])>-1) llOwnerSay("ERROR! You have two groups notecards where the name \""+llGetSubString(name,nameStarts,-1)+"\" is used for the button! Group button names must be unique");
            else invGroups=[]+[name,(integer)(llGetSubString(name,7,nameStarts-3)),llGetSubString(name,nameStarts-2,nameStarts-2),llGetSubString(name,nameStarts,-1)]+invGroups;
        }
        else if (llSubStringIndex(name,".NPC")==0)
        {
            if (llListFindList(invNpc,[llGetSubString(name,8,-1)])>-1) llOwnerSay("ERROR! You have two NPC notecards where the NPC name is \""+llGetSubString(name,8,-1)+"\" but NPC names must be unique");
            else invNpc=[]+[name,llGetSubString(name,6,6),llGetSubString(name,8,-1)]+invNpc;
        }
        else if (llSubStringIndex(name,gs_ConfigName)==0) { gi_HaveConfig=1;}
    }
}

// *** ANIMATIONS GRUPPEN NOTECARD SPEICHERN
saveCard(string cardName)
{
    if (llGetInventoryType(cardName)==INVENTORY_NOTECARD)
    {
        llRemoveInventory(cardName);
        llSleep(0.25);
    }
    integer i;
    integer l=llGetListLength(anData);
    string dataToStore;
    while (i<l)
    {
        dataToStore+=llDumpList2String(llList2List(anData,i,i+anStride-1),"|")+"\n";
        i+=anStride;
    }
    osMakeNotecard(cardName,dataToStore);
    llMessageLinked(LINK_THIS,0,"GLOBAL_EDIT_STORE_TO_CARD|"+cardName,llDumpList2String(positions,"|"));
}

// *** DIE LINKNUMMER DES AVATARS HERAUSFINDEN UND ZURÜCKMELDEN
integer getUserLink(key who)
{
    integer ret=FALSE;
    if (who!=NULL_KEY)
    {
        integer link=llGetNumberOfPrims();
        while ((link>1) && (ret==FALSE))
        {
            key this=llGetLinkKey(link);
            if(this==who) ret=link;
            link--;
        }
    }
    return ret;
}

// *** MENÜ DIALOG MIT USER INITIALISIEREN
startListening()
{ llDialog(user,txtDia,llList2List(butDia,9,11)+llList2List(butDia,6,8)+llList2List(butDia,3,5)+llList2List(butDia,0,2),myChannel);}

// *** RÜCKMELDUNG AUTOMODE TIMER EINSTELLUNG UND AKTUELLER ANIMATION
string currentlyPlaying()
{
    string strToReturn="Currently playing: "+llList2String(currentAn,0)+" > "+llList2String(currentAn,1);
    if (autoOn) strToReturn+="\nAUTO mode is on and set to "+(string)llRound(autoTimer)+" seconds";
    return strToReturn;
}

// *** NACH AVA POSITIONSEINSTELLUNG DIE NEUEN ORTSWERTE ZURÜCKSCHREIBEN
persistChanges()
{
    integer u=llGetListLength(positions);
    while(--u>=0)
    {
        list avData=getPosition(llList2Key(positions,u),getUserLink(llList2Key(positions,u)));
        vector pos=llList2Vector(avData,0);
        rotation rot=llList2Rot(avData,1);
        string strPos="<"+trimF(pos.x)+","+trimF(pos.y)+","+trimF(pos.z)+">";
        string strRot="<"+trimF(rot.x)+","+trimF(rot.y)+","+trimF(rot.z)+","+trimF(rot.s)+">";
        currentAn=[]+llListReplaceList(currentAn,[strPos,strRot],4+u*3,5+u*3);
    }
    integer anIndex=llListFindList(anData,llList2List(currentAn,1,1));
    if(gi_NC_PROP_CHANGED)
    {    // NC_PROPS
    string old_cmd=llList2String(currentAn,2);
        integer NC_PROP_data_start=llSubStringIndex(old_cmd,"NC_PROP{")+8; // find start
        // test is little weird, as i added +8 to compensate for search string length
        if (NC_PROP_data_start != 7)
        {    // search ending delimiter in rest of string
            integer NC_PROP_data_end=NC_PROP_data_start+llSubStringIndex(llGetSubString(old_cmd, NC_PROP_data_start,-1),"}");
            string new_cmd=llGetSubString(old_cmd, 0, NC_PROP_data_start -1) + gs_NC_PROP_DATA + llGetSubString(old_cmd, NC_PROP_data_end,-1);
            currentAn=[]+llListReplaceList(currentAn,[new_cmd],2,2);
        }
        gi_NC_PROP_CHANGED=FALSE;
    }
    anData=[]+llListReplaceList(anData,llList2List(currentAn,1,-1),anIndex,anIndex+anStride-1);
    llMessageLinked(LINK_THIS,0,"GLOBAL_EDIT_PERSIST_CHANGES",llDumpList2String(positions,"|"));
}

// *** HANDLES ZUR AVA POSITIONEN EDIT REZZEN
rezHandles()
{
    if (llGetListLength(editHandles)<llGetListLength(positions)) llRezObject(handleName,llGetPos(),ZERO_VECTOR,ZERO_ROTATION,0);
    else
    {
        rezzingHandles=FALSE;
        integer h=llGetListLength(editHandles);
        while (--h>=0) { osSetPrimitiveParams( llList2Key(editHandles,h),[PRIM_SIZE,handleSize,PRIM_COLOR,ALL_SIDES,llList2Vector(handleColours,h%llGetListLength(handleColours)),handleAlpha,PRIM_TEXT,"pos "+(string)(h+1),llList2Vector(handleColours,h%llGetListLength(handleColours)),1.0,PRIM_NAME,"pos "+(string)(h+1)]); }
        playAnimation(llList2String(currentAn,1));
        llSetTimerEvent(editTimer);
        SyncAvas();
        showEditMenu();
    }
}

// *** HANDLES ZUR AVA POSITIONEN EDIT ENTFERNEN
removeHandles()
{
    llSetTimerEvent(0.0);
    myState="RUNNING";
    llMessageLinked(LINK_THIS,0,"GLOBAL_NOTICE_LEAVING_EDIT_MODE",llDumpList2String(positions,"|"));
    integer l=llGetListLength(editHandles);
    while (--l>=0) { osMessageObject(llList2Key(editHandles,l),"HANDLE_DIE");}
    editHandles=[];
    showOptionsMenu();
}

// *** HANDLES ZUR AVA POSITIONEN EDIT VERSCHIEBEN/POSITIONIEREN
setHandle(key prim, vector relPos, rotation relRot)
{
    vector pos=relPos*llGetRot()+llGetPos();
    rotation rot=relRot*llGetRot();
    osSetPrimitiveParams(prim,[PRIM_POSITION,pos,PRIM_ROTATION,rot]);
}

// *** AVATAR AN ANDERE POSITION FÜR NEUE ANIMATION BEFÖRDERN
setPosition(key who, integer link, vector pos, rotation rot)
{
    vector size = llGetAgentSize(who);
    float fAdjust = ((((0.008906 * size.z) + -0.049831) * size.z) + 0.088967) * size.z;
    llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL, ((pos + <0.0, 0.0, 0.4>) - (llRot2Up(rot) * fAdjust)), PRIM_ROT_LOCAL, rot]);
}

// *** AKTUELLE AVATARPOSITION ERMITTELN
list getPosition(key who, integer link)
{
    vector size = llGetAgentSize(who);
    float fAdjust = ((((0.008906 * size.z) + -0.049831) * size.z) + 0.088967) * size.z;
    list avData=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
    vector avPos=llList2Vector(avData,0);
    rotation avRot=llList2Rot(avData,1);
    vector avPosUnadjusted=(avPos - <0.0, 0.0, 0.4>) + (llRot2Up(avRot) * fAdjust);
    return [avPosUnadjusted,avRot];
}

// *** REGIONS POSITION IN RELATIVE POSITION UMRECHNEN
list regToRel(vector regionPos,rotation regionRot)
{
    vector relPos=(regionPos - llGetPos()) / llGetRot();
    rotation relRot=regionRot/ llGetRot();
    return [relPos,relRot];
}

// *** RELATIVE POSITION IN REGIONS POSITION UMRECHNEN
list relToReg(vector refPos,rotation refRot)
{
    vector regionPos=refPos*llGetRot()+llGetPos();
    rotation regionRot=refRot*llGetRot();
    return [regionPos,regionRot];
}

// *** HILFSFUNKTION ZUR POSITIONS BERECHNUNG
string trimF(float value)
{
    integer newVal=llRound(value*10000);
    integer negFlag=FALSE;
    if (newVal<0) { negFlag=TRUE; newVal*=-1; }
    integer strLength;
    string retStr;
    if (newVal==0) retStr="0";
    else if (newVal<10) retStr="0.000"+(string)newVal;
    else if (newVal<100) retStr="0.00"+(string)newVal;
    else if (newVal<1000) retStr="0.0"+(string)newVal;
    else if (newVal<10000) retStr="0."+(string)newVal;
    else
    {
        retStr=(string)newVal;
        strLength=llStringLength(retStr);
        retStr=llGetSubString(retStr,0,strLength-5)+"."+llGetSubString(retStr,strLength-4,strLength-1);
    }
    while (llGetSubString(retStr,strLength,strLength)=="0")
    {
        retStr=llGetSubString(retStr,0,strLength-1);
        strLength-=1;
    }
    if (negFlag) retStr="-"+retStr;
    return retStr;
}

// NPC im GRUPPENKONTEXT rezzen, auch für public gesperrte Sims. Mit NPC Userprofilinfo und Profilbild
key npc_rezzer(string npcnotecard, key sittarget, vector npcPos)
{
    string npc_name = llGetSubString(npcnotecard,8,-1); // NPC Namen ermitteln
    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
    }
    return npctorez;
}

// *** HAUPTMENÜ
default
{
    // *** INITIALISIERUNG UND GRUNDLIEGENDE ÜBERPRÜFUNG
    state_entry()
    {
        if (llGetAttached()) return;
        if (llGetLinkNumber()>1)
        {
            myState="ERROR";
            llOwnerSay("ERROR! The main PMAC controller script must always be located in the root prim of a linkset!");
            return;
        }
        myChannel=0x80000000|(integer)("0x"+(string)llGetKey());
        user=NULL_KEY;
        buildInventoryLists();
        if (gi_HaveConfig) loadConfig();
        if (llGetInventoryType(baseAn)!=INVENTORY_ANIMATION)
        {
            llOwnerSay("ERROR! Unable to find the base priority 1 animation to use for synch: "+baseAn);
            myState="ERROR";
            return;
        }
        if (llListFindList(invGroups,[defaultGroup])==-1)
        {
            myState="ERROR";
            llOwnerSay("ERROR! Unable to find the specified default group \""+defaultGroup+"\" in inventory. Make sure you supplied the simple group name, not the full card name");
            return;
        }
        loadAnimGroup(defaultGroup);
        integer i=llList2Integer(invGroups,llListFindList(invGroups,[defaultGroup])-2);
        positions=[];
        while (--i>=0) { positions=[]+positions+[NULL_KEY]; }
        currentAn=[]+[currentGroup]+llList2List(anData,0,anStride-1);
        myState="READY";
        llMessageLinked(LINK_THIS,0,"GLOBAL_SYSTEM_RESET",NULL_KEY);
        llSitTarget(<0.0,0,0.001>,ZERO_ROTATION);
        if (!silent) llOwnerSay("Initialization complete and ready to use");
    }

    // *** INITIALER RESET BEIM REZZEN DES POSERS
    on_rez(integer num) {llResetScript();}

    // *** HILFSOBJEKTE FÜR EDITMODUS REZZEN
    object_rez(key id)
    {
        if (!rezzingHandles) return;
        editHandles=[]+editHandles+[id];
        rezHandles();
    }

    // ***
    sensor(integer num)
    {
        llOwnerSay("ERROR! Sensor event inexplicably returned a result!");
        llSensorRemove();
        autoOn=FALSE;
    }

    // ***
    no_sensor()
    {
        if (!autoOn)
        {
            llOwnerSay("ERROR! Sensor repeat triggered but auto mode is off. Figure out how this can happen and fix. Sensor removed");
            llSensorRemove();
            return;
        }
        if (myState!="RUNNING")
        {
            llOwnerSay("ERROR! Sensor repeat triggered while not in normal running state: Please figure out how this happened and fix. Sensor removed and auto turned off.\nState was=: "+myState);
            autoOn=FALSE;
            llSensorRemove();
            return;
        }
        integer i=llListFindList(anList,[llList2String(currentAn,1)]);
        if (i==-1) i=0;
        else
        {
            i++;
            if (i>=llGetListLength(anList)) i=0;
        }
        playAnimation(llList2String(anList,i));
    }

    // *** PERIODISCHE PRÜFUNG EDIT MODUS ; ansonsten TIMER löschen
    timer()
    {
        if(myState=="EDIT")
        {
            llSetTimerEvent(0.0);
            integer l=llGetListLength(positions);
            while (--l>-1)
            {
                key who=llList2Key(positions,l);
                if (who==NULL_KEY)
                {
                    llOwnerSay("ERROR! NULL_KEY user while processing timer event edit mode. Leaving edit mode without saving changes.");
                    removeHandles();
                    return;
                }
                if (llGetAgentSize(who)==ZERO_VECTOR)
                {
                    llOwnerSay("ERROR! Cannot detect user in region while processing timer event edit mode. Leaving edit mode without saving changes");
                    removeHandles();
                    return;
                }
                list handleData=llGetObjectDetails(llList2Key(editHandles,l),[OBJECT_POS,OBJECT_ROT]);
                if (llGetListLength(handleData)==0)
                {
                    llOwnerSay("ERROR! Unable to detect a handle! Leaving edit mode without saving changes");
                    removeHandles();
                    return;
                }
                handleData=[]+regToRel(llList2Vector(handleData,0),llList2Rot(handleData,1));
                setPosition(who,getUserLink(who),llList2Vector(handleData,0),llList2Rot(handleData,1));
            }
            llSetTimerEvent(editTimer);
        } else llSetTimerEvent(0.0);
    }

    // *** ABHANDLUNG DES PMAC REMOTEKOMMANDOS
    dataserver(key qid, string message)
    {
        if ((ownerOnlyRemote) && (llGetOwnerKey(qid)!=llGetOwner())) return;
        if (llSubStringIndex(message,"PMAC_REMOTE_")==0) handleRemoteCall(message);
    }

    // *** NACHRICHTEN VON LINKOBJEKTEN AUSWERTEN
    link_message(integer sender,integer flag,string message,key command)
    {
        if (flag!=-1) return;
        if (message=="MAIN_RESUME_MAIN_DIALOG") showOptionsMenu();
        else if (llSubStringIndex(message,"MAIN_REGISTER_MENU_BUTTON")==0)
        {
            string buttonName=llList2String(llParseString2List(message,["|"],[]),1);
            integer locationToAdd=llListFindList(specials,[buttonName]);
            if (locationToAdd==-1) specials=[]+specials+[buttonName,command];
            else specials=[]+llListReplaceList(specials,[buttonName,command],locationToAdd,locationToAdd+1);
            specials=[]+llListSort(specials,2,TRUE);
        }
        else if (llSubStringIndex(message,"MAIN_UNREGISTER_MENU_BUTTON")==0)
        {
            string buttonName=llList2String(llParseString2List(message,["|"],[]),1);
            integer locationToKill=llListFindList(specials,[buttonName,command]);
            if (locationToKill==-1) return;
            else specials=[]+llDeleteSubList(specials,locationToKill,locationToKill+1);
            specials=[]+llListSort(specials,2,TRUE);
        }
        else if (llSubStringIndex(message,"NC_PROP_UPDATE")==0)
        { // NC_PROP addon
            gi_NC_PROP_CHANGED=TRUE;
            gs_NC_PROP_DATA=llGetSubString(message,15,-1);
        }
        else if (llSubStringIndex(message,"PMAC_REMOTE_")==0) handleRemoteCall(message);
    }

    // *** ANZAHL SITZENDER USER HAT SICH GEÄNDERT; ODER BESITZERWECHSEL DES POSERS
    changed (integer change)
    {
        if (change & CHANGED_LINK)
        {
            if (llGetLinkNumber()>1)
            {
                llOwnerSay("ERROR! You have changed the linkset and the PMAC main script is no longer located in the root prim!");
                myState="ERROR";
                return;
            }
            integer i=llGetNumberOfPrims();
            integer l=llGetObjectPrimCount(llGetKey());
            list seated;
            integer realAvi;
            while (i>l)
            {
                key who=llGetLinkKey(i);
                if ((myState=="ERROR") || (myState=="INITIALIZING"))
                {
                    if (osIsNpc(who)) osNpcRemove(who);
                    else
                    {
                        if (myState=="ERROR") llRegionSayTo(who,0,"Sorry, I have encountered an error and must shut down until it is corrected");
                        else llRegionSayTo(who,0,"Sorry, you cannot sit while I am initializing. Please wait a moment and try again.");
                        llUnSit(who);
                    }
                }
                else
                {
                    seated=[]+[who]+seated;
                    if (!osIsNpc(who)) realAvi++;
                    if (llListFindList(positions,[who])==-1)
                    { // new sitter
                        integer indexToSit=llListFindList(positions,[NULL_KEY]);                
                        if (ownerUseReq && (who!=llGetOwner()) && (llListFindList(positions,[llGetOwner()])==-1))
                        {
                            llRegionSayTo(who,0,"Sorry, the system is set to require that the owner is using me before anyone else may sit.");
                            llUnSit(who);
                        }
                        else if (indexToSit==-1)
                            {
                                llRegionSayTo(who,0,"Sorry, there are no available positions for you to occupy. Please wait for someone to stand");
                                llUnSit(who);
                            }
                        else
                        {
                            positions=[]+llListReplaceList(positions,[who],indexToSit,indexToSit);
                            llSleep(0.2);
                            list anToStop=llGetAnimationList(who);
                            osAvatarPlayAnimation(who,baseAn);
                            integer stop=llGetListLength(anToStop);
                            key dontStop=llGetInventoryKey(baseAn);
                            while (--stop>-1) { osAvatarStopAnimation(who,llList2Key(anToStop,stop)); }
                            if (myState=="READY")
                            {
                                if ((osIsNpc(who)) && (!allowSoloNPC))
                                {
                                    llSay(0,"Sorry, an NPC cannot sit until there is a human user in control. Unsitting your NPC.");
                                    llUnSit(who);
                                    positions=[]+llListReplaceList(positions,[NULL_KEY],indexToSit,indexToSit);
                                    osAvatarStopAnimation(who,baseAn);
                                }
                                else
                                {
                                    myState="RUNNING";
                                    llMessageLinked(LINK_THIS,0,"GLOBAL_START_USING",llDumpList2String(positions,"|"));
                                    playAnimation(llList2String(currentAn,1));
                                }
                            }
                            else { playAnimation(llList2String(currentAn,1));}
                            PositioniereAva(indexToSit, who);  // Geschlechtsspezifische Positionierung
                        }
                    }
                }
                i--;
            }
            i=llGetListLength(positions);
            while (--i>=0)
            {
                key who=llList2Key(positions,i);
                if (who!=NULL_KEY)
                {
                    if ((!realAvi)&&osIsNpc(who))
                    {
                        if (!allowSoloNPC)
                        {
                            osNpcRemove(who);
                            positions=[]+llListReplaceList(positions,[NULL_KEY],i,i);
                        }
                    }
                    else if (llListFindList(seated,[who])==-1)
                    {
                        if (myState=="EDIT")
                        {
                            llOwnerSay("WARNING! Someone stood! Leaving edit mode and no changes will be stored to card");
                            removeHandles();
                            if (who!=llGetOwner())showOptionsMenu();
                        }
                        if (llGetAgentSize(who)!=ZERO_VECTOR)
                        {
                            osAvatarPlayAnimation(who,"stand");
                            osAvatarStopAnimation(who,llList2String(currentAn,3+i*3));
                            osAvatarStopAnimation(who,baseAn);
                            if (who==user) user=NULL_KEY;
                        }
                        positions=[]+llListReplaceList(positions,[NULL_KEY],i,i);
                        llMessageLinked(LINK_THIS,0,"GLOBAL_USER_STOOD|"+(string)i+"|"+(string)who,llDumpList2String(positions,"|"));
                    }
                }
            }
            if (!realAvi)
            {
                if (diaHandle)
                {
                    llListenRemove(diaHandle);
                    diaHandle=FALSE;
                }
                if (llGetListLength(seated)<1)
                {
                    if (autoOn) llSensorRemove();
                    myState="READY";
                    llMessageLinked(LINK_THIS,0,"GLOBAL_SYSTEM_GOING_DORMANT",NULL_KEY);
                    if (resetOnQuit) llResetScript();
                }
            }
        }
        else if (change & CHANGED_REGION_START) {if(resetOnSimcross) llResetScript();}
        else if (change & CHANGED_OWNER) llResetScript();
    }
   
    // *** MENÜ DURCH BERÜHREN DES POSERS ANGEFORDERT
    touch_start(integer num)
    {
        toucher=llDetectedKey(0);
        integer gruppe = llDetectedGroup(0);
        integer access = BerechtigungsCheck(toucher,gruppe);

        if (osIsNpc(llDetectedKey(0))) return;
        if (myState=="ERROR")
        {
            if (toucher==llGetOwner()) llOwnerSay("PMAC somehow entered ERROR state. Please check your chat log for one or more messages indicating the nature of the error, correct it, then reset the script");
            else llRegionSayTo(toucher,0,"Sorry, I encountered an error and am waiting for the owner to correct the issue and restart me");
        }
        else if (myState=="INITIALIZING") llRegionSayTo(toucher,0,"Please wait until initialization is complete, then try again");
        // else if (myState=="READY") llRegionSayTo(toucher,0,"Please sit to begin using me");
        else if (myState=="EDIT")
        {
            if (toucher!=llGetOwner()) llRegionSayTo(toucher,0,"Sorry, the owner is currently editting positions and must remain in control of the dialog until this is complete.");
            else startListening();
        }
        else if (myState=="RUNNING")
        {
            if ((!access) && (llListFindList(positions,[toucher])==-1)) llRegionSayTo(toucher,0,"Only current users may access the controls. Please sit, then try again");
            else if ((!access) &&(ownerOnlyMenus && (toucher!=llGetOwner()))) { if (!silent) llRegionSayTo(toucher,0,"Sorry, this item is currently set to only allow the owner to access the controls.");}
            else if (toucher!=user)
            {
                if (user==NULL_KEY)
                {
                    if (!diaHandle) diaHandle=llListen(myChannel,"",NULL_KEY,"");
                    ChangeMenuUser(toucher);
                }
                else llDialog(toucher,"Please confirm that you want to take control of me",["TAKE CONTROL","CANCEL"],myChannel);
            }
            else startListening();
        }
    }


TEIL2: "P607 PMAC 2.8 Poser UNIVERSAL + NPC 122022.lsl" befindet sich im nächsten Artikel!!!!!!!

Drucke diesen Beitrag

  Praktische Tricks die uns das Leben in OpenSim
Geschrieben von: ThunderTower - 12.02.2024, 19:14 - Forum: Animieren - Antworten (9)

Praktische Tricks die uns das Leben in OpenSim etwas leichter machen!

Verknüpfen von PMAC-Controller und beliebigen Objekten

Verknüpfungen mit dem Multi-Animation Controller und einem Objekt (z.B. Bett, Stuhl etc.) müssen korrekt sein.

Nur so stellt man eine einwandfreie Funktion sicher.

Voraussetzungen:

Man muss Eigentümer vom Objekt und auch vom PMAC-Controller sein. Möchte man bei der späteren Einrichtung von Animationen und Avataren keine Probleme haben,

empfiehlt es sich den PMAC-Controller wirklich auf 90,180,270 auszurichten. Zumindest sehe ich das so. Verknüpft wird das Objekt (Bett, Stuhl) mit dem Controller welcher

vorher auf NICHT sichbar gestellt wurde. Ich verknüpfe also das Objekt mit der unsichtbaren Fläche (PMAC-Controller). Dabei wandert der komplette Inhalt vom Controller in das Objekt.

Diese blaue grafische Benutzeroberfläche vom Controller ist nach der Verknüpfung an beliebiger Stelle am Objekt verfügbar. Der Controller selbst ist jetzt natürlich unsichtbar.

Jetzt können Animationen eingefügt oder die Note bearbeitet werden.

   

Das war's eigentlich schon.

Drucke diesen Beitrag

  Beim laden einer OAR die Objekte der Landgruppe übertragen
Geschrieben von: Tron Mcp - 10.02.2024, 17:41 - Forum: Serversoftware - Antworten (2)

Ich kämpfe eben mit  der Installation eines Backupgrids.

Dabei möchte ich gerne alle Objekte beim laden der OAR gleich der Landbruppe der Sim übertragen.

Bisher ist mir das nur einmal per Zufall geglückt. Es scheint also prinzipiell möglich zu sein.
Hat jemand einen Idee wie das gezielt geht?

Drucke diesen Beitrag

  Probleme bei Mesh Häuser, Höhlen und dergleichen
Geschrieben von: Trawell - 09.02.2024, 12:46 - Forum: Serversoftware - Antworten (5)

Hi
und das nächste Fehlverhalten fällt mir gerade auf.
Bei Höhlen, Ruinen und solches kann ich nicht durchlaufen.
Die Eigenschaft sind weder Prim noch Konvexe Hülle (Prim steht gar nicht zur Auswahl), sondern sind bei Keiner.
Also genau gleich eingestellt wie beim Windows Server.

Ich gehe mal davon aus das dies eine Einstellung in einer der Ini Dateien sein könnte?

Eventuell hat jemand eine Idee.

Viele Grüße
Trawell

Drucke diesen Beitrag

  Fehler nach OAR Import und Region Neustart
Geschrieben von: Trawell - 09.02.2024, 12:20 - Forum: Serversoftware - Keine Antworten

Hallo zusammen,
ich bin grad am Testen einer Linux Installation.
Nach dem Laden einer OAR habe ich bemerkt, das dieser Opensimulator Prozess fast 7 GB RAM braucht, was ich etwas hoch finde.
Nun, könnte ja sein das dies vom Hochladen der OAR kommt.
Also starte ich die Region neu und habe folgenden Fehler:
[WARNING]: EOC marker not found. Codestream is corrupted.

Kann mir jemand sagen woher das kommt und wie ich dies beheben könnte?
Irgendwas hab ich gelesen wegen JPEG Formaten, schnall das aber grad nicht.

Zudem wenn ich die Map Generierung von Warp3dImageModule auf MapImageModule ändere, habe ich diesen Fehler nicht.

Vielen Dank und Grüße
Trawell

Drucke diesen Beitrag

  Ab 14.2 keine epub Bücher mehr
Geschrieben von: Cheryl Furse - 07.02.2024, 17:18 - Forum: Informationen und aktuelle Meldungen - Keine Antworten

Hello everyone

Announcement: You can't get epub books and movie streams after 14th February on Big City Life and Decadence sim anymore. The server will be down after the 14th February. If you want to get BDSM related epub books (Maledom, Femdom, general, educational) or scifi fantasy books you should go now on Big City Life to the airport at gate 3-4 upper floor. Or on Decadence sim on mainland at the big tower. After the 14th February you will only see videos I produced and not movies anymore in all cinemas. But there will be still streams of "Secretary", "The pet" and "preaching to the pervert" .



Angehängte Dateien Thumbnail(s)
   
Drucke diesen Beitrag

  Apples Edge KI
Geschrieben von: Cheryl Furse - 07.02.2024, 12:12 - Forum: Informationen und aktuelle Meldungen - Keine Antworten

Hallo zusammen

gestern stand im Handelsblatt ein zweiseitiger Artikel über die KI Geheimpläne von Apple. Hier online nur die ersten Zeilen. Muss man aboniert haben um es zu lesen. Ist Bezahlschranke.

https://www.handelsblatt.com/technik/it-...10138.html

Habe aber die Papierausgabe gelesen. Hier mal etwas zusammengefasst, wie apple neue wege geht.

Da apple immer ein optimiertes rundum Paket aus Hardware und Software, wird es jetzt genauso bei KI laufen. Durch die 3 nm M Prozessoren wird es jetzt auch hardwaremässig möglich sein, wie auch bei dem spatialen Computer VisionPro. (also das was die meisten nur als headset sehen ist aber ein kompletter Computer ohne Monitor, Keyboard oder Maus. Die Skibrille ist also kein headset sondern ein neuartiger Computer)

Bei der KI wird es genauso laufen und KI wird nur noch lokal sein ohne, dass es eine Internetanbindung braucht. Also genau das was auch bei GPT4all schon möglich ist. Bei apple wird es aber weiter gehen. AI ist dann nicht einfach ein "assistent" sondern wird automatisch die Programme bedienen. Wenn apple schon soweit ist mit der AI dass es auch mathematische Modelle entwickeln kann und selber rechnen und entwickeln kann, also auch Analysen machen kann als AGI, dann wird es eine eigene Intelligenz sein. ChatGPT ist nur ein Sprachmodell, was in Wirklichkeit nicht intelligent ist sondenr nur so tut als ob. Es kann nicht selber rechnen und analysen machen. Es folgt nur einem Model, was man vorher trainiert hat. Es besteht zwar den Touring test, aber ist nur eine Simulation.

Apples Pläne gehen weiter. Und das rein nur mit dem lokalen Computer ohne Internetanbindung. Also im Sinne von dezentralität wie opensim ...

Wahrscheinlich läuft es darauf hinaus, dass man dann mit VisionPro eine Holofigur im AR sieht und mit ihr spricht, die dann alles ausführt. Man sagt dann einfach nur "mach dieses oder jenes" und die KI führt dann jeweils passend die Programme aus, die es ermöglicht.

Man klickt dann also nicht mehr auf ein Prgramm start button sondern die KI macht dann alles so wie sie es braucht und nutzt die Programme für ihrne Auftrag.

Wir kennen ja mittlerweile schon KI programme wie Genie die dann text to 3D mesh objekte generiert. Also wir sagen einfach was wir haben wollen als mesh modell und das programm generiert es in fast realtime.

Das würde dann mit Apples edge KI alles voll integriert sein und alles komplett lokal nur auf dem Computer passieren. Keine Internetanbindung. Für aufwändigere sachen auf eigener cloud abgelegt. Speicher braucht es auch und würde dann von anderen eigenen Geräten abrufbar sein. Es wäre aber nur eigener Zugriff und von keinem anderen möglich.

Die tests laufen schon seit dem M1 Max und seit dem M3 mit 3 nm technologie ist es jetzt Spruchreif und ausgereift. Bis jetzt hat Apple noch hinter dem Berg gehalten und nichts nach aussen dringen lassen. Hat erstmal alle anderen mit stümperhafter Software machen lassen, aber kommt bald selbst auf dem Markt mit ausgereifter KI

Ist ähnlich wie es beim iphone war oder jetzt visionPro als eigenem Computer und nicht nur als Headset, was Kopfschmerzen verursacht bei längerem Gebrauch.

wird spannend werden und ganz im Sinne der Dezentralität ohne Internet Abhängigkeit.

Drucke diesen Beitrag

  Vorsicht ANYDESK wurde gehackt- Risiko das euer Rechner übernommen wird
Geschrieben von: Tron Mcp - 04.02.2024, 14:58 - Forum: Sicherheitssoftware und Hersteller - Antworten (10)

ANYDESK Gehackt, Gefahr das eure Rechner übernommen werden, wenn ihr eine der bisherigen Versionen installiert habt.

Gestern, 03.02.2024 kamen erste Meldungen auf verschiendenen Portalen:

Der Anbieter von Remotelösungen Anydesk wurde gehackt. Der Vorfall scheint noch nicht abgeschlossen zu sein.

https://www.golem.de/news/cyberangriff-f...81848.html

Wenn ihr Anydesk installiert habt, solltet ihr es umgehen deinstallieren und abwarten bis Entwarnung gegeben, sowie eine neue Version verfügbar ist.


Warum ist das für euch gefährlich?

Nun Anydesk ist eine "Man in the Middle Lösung". 
Jeder Rechner der das installiert hat meldet sich periodisch bei Anydesk das er verfügbar wäre.

Sobald jemand eine Verbindung zu euch aufnehmen will, meldet er sich bei Anydesk an, und diese vermittlen weiter.
Das ist der Grund warum es auch bei aktivierter NAT daheim noch funktioniert.

Für beide Seiten sieht es so aus wie wenn sie zu Anydesk initial die verbindung aufnehmen.

ABER: In diesem Falle bedeutet das, das die erfolgreichen Angreifer versuchen könnten als Anydesk ausgegeben auf euren Rechner zugreifen.
Deswegen hat Anydesk auch die bisher genutzen Zertifikate für ungültig erklärt.
Aber sie sind noch am kämpfen, und die Nachrichtenlage ist noch nicht vertrauenswert.


Wie bekommt ihr das unter Linux deinstalliert?

1. Der laufende Client muss gestoppt werden. Dieses geschieht in Mint über das in der rechten unteren Ecke eingeblendeten Logo. Rechtsklick drauf - beenden.
Nun verschwindet das Logo.  Danach wäre euer Rechner sicher, aber beim nächsten Rechnerstart habt ihr wieder die unsichere Version laufen.

2. Nun deinstalieren wir die Software indem wir über "LM - Internet" - dann Rechtsklick auf Anydesk ausführen. Wir sehen die Option "deinstallieren" und klicken drauf.
Nun erfolgt die Passwort Abfrage eures Users, und anschließend die Deinstallation.


Wenn es eine Fehlermeldung gibt, dann öfnet man die Konsole, und meldet sich mit "su root" an und  gibt sein root Passwort ein.
Danach gibt man diese Zeile ein:       apt --fix-broken install      und bestätigt alle Anfragen.
Nun sollte die obige Deinstallation gehen.

Anmerkung zu Anydesk:

Die Lösung an sich ist super, und extrem zuverlässig. Dumm finde ich die Informationsblockade durch Anydesk. 
Die hätten von sich aus schneller warnen müssen, da es alle ihre Kunden betrifft. Das hätte Vertrauen geschaffen.

Dennoch werde ich es wieder einsetzten sobald es wieder sicher ist.

Drucke diesen Beitrag

  Alltagstauglichkeit von NPC companion
Geschrieben von: Cheryl Furse - 04.02.2024, 12:15 - Forum: Informationen und aktuelle Meldungen - Keine Antworten

Hallo zusammen

Der NPC Companion von Valerie hat ein neues update bekommen, was nun auch gut für meine Bedürfnisse funktioniert. Es funktioniert sogar auf meinem riesen sim super und man kann ihn jetzt mit schnellen clicks einfach bedienen. Noch hat er keine AI eingebaut. Aber das kommt noch. Er soll auch text to speech bekommen. Hier mein kleiner Alltagstest von gestern mit Dean Winchester.

Sight seeing tour on Big City Life with NPC Companion Dean Winchester. Wanted to show him his new home. 
   
Although Dean can't speak yet, he was already headstrong today. He didn't want to sit with me on the upper deck of the ship and I had to ask the captain if he could put a chair above the root prim for Dean. Because Dean just wanted to sit there.
   
   
  But we went to the zoo anyway. Only I had to sit up there alone and Dean looked more like we were on a fishing vacation. lol
   
When we arrived at the zoo everything went well, and I could lead Dean well through the people and small paths 
   
but when we wanted a cab it was difficult. As in real life, a cab never comes when you need it. In the area there are only 3 cars at the zoo anyway and only every 34 minutes because they have the longest routes. 
   
We had to walk to the horse racecourse and then we were lucky 
   

and drove to the Beach Cafe on the other side of the 7x7 sim. 
   

where Lady Trinity, Arielle, Kitty, Judy and Jimmy appeared suddenly some minutes through a "magic cube" (HG teleport script of Sergio Rodriguez). We had long talks with coffee there about NPCs and AI and text to speech script. Of course a lot more than this. Dean couldn't disturb us. If he would have AI already implanted he would have lead the talks, of course lol
   

Drucke diesen Beitrag

  Maria und Lukas suchen ....
Geschrieben von: ThunderTower - 02.02.2024, 18:06 - Forum: malugrid.eu - Keine Antworten

Hallo liebe Leser,

Maria und Lukas suchen für unsere Rumpelbude einen männlichen oder weiblichen DJ!

Welcher DJ hat Interesse bei uns an verschiedenen Wochenenden ab 20:00 Uhr aufzulegen?

Wir lieben so diese Richtungen:

Rock, Softrock, Rock Classics, Blues, Gothic, Oldies, Pop, Schlager, Disco, House usw.

Personen unter 18 Jahren dürfen sich bei uns NICHT aufhalten und werden sofort entfernt.

Unser Dresscode für Damen und Herren:

Angemessen, entsprechend zum Club

Mit eigenem Live Stream (lizensiert) und bei Interesse bitte PN hier im Forum oder schreibt uns einfach Inworld an.

Vielen Dank

Happy

Drucke diesen Beitrag