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.

PKW SCRIPT für BULLET in OPENSIM
#1
PKW SCRIPT für BULLET in OPENSIM

Version 3.01 Stand 24.08.2022.

Nachdem die Neuentwicklung meines Motorrad Script gut angekommen ist, ergänze ich dies um eine Anpassung für PKWs.
Es ist vom Stil an das Motorrad Script angelehnt, jedoch in der Fahrdynamik eigenständig um einen maximalen Fahrspaß bei simpler Bedienung zu ermöglichen.
Das Script ist explizit für langsame Stadtfahrzeuge optimiert, um ein präzises Fahren selbst auf kleinen Strassen zu ermöglichen.

Diesmal auf Moes Wunsch mit integrierten Fahrer Berechtigungs Check, damit Stella Herzchen auch mal fahren darf.
Schliesslich ist dieses Scritp perfekt damit Stella mit ihrem Stadtautochen zum Einkaufen fährt, und die Kinder zur Schule bringt.
Ich hätte diesmal ja sogar fast ein Autoradio eingebaut damit die Kinder auf dem Wege zur Schule "Käpten Blaubär" hören können, habs mir aber verkniffen.

Es ermöglicht Fahrberechtigungen nach folgenden Usergruppen zu setzten:
- Der Inhaber des Fahrzeugscheins (Besitzer) darf immer
- Die Ehefrau kann per UUID explizit im Script aufgeführt werden. Ebenso der 18jährige Bengel der Mamas Auto benutzen darf.
- Karrensharing innerhalb der gleichen Gruppe wird auch unterstützt.
- Und wenn ihr den Zündschlüssel stecken klassen wollt, dann kann jeder das Fahrzeug nutzen.


Wie immer gilt:
Es darf frei in Opensim verbeitet werden, aber nicht gegen Geld verkauft werden. Der Hinweis auf mich als Autor ist zu belassen.
Verkauf und Veröffentlichung in SL ist alleinig mir vorbehalten.


Wer schon das Bike script kennt braucht nun nicht weiterzulesen, und kann es direkt einsetzten.

Für alle Einsteiger aber noch mal eine angepasste Zusammenfassung was das Script bietet, und wie es einzusetzen ist:


FAHREN:

- das Auto hat 5 Vorwärtsgänge, Leerlauf und Rückwärtsgang.
- es gibt Unterstützung für schnelle Schaltvorgänge.
  Bremst man bei hoher Geschwindigkeit schaltet das Auto einen Gang herab um besseres Fahrverhalten und höhere Beschleunigung zu erzielen.
- Fahrparameter ändern sich dynamisch in Abhängigkeit von Gang und Fahrtgeschwindigkeit.
  Dies gilt für Lenkung, Kurvenneigung, Spurtreue, Radhaftung
- Es gibt einen Leerlauf in dem das Auto nicht physisch ist. Auch wird in diesem Modus getankt.

FAHRERANIMATIONEN:
- Es wird pro Gang eine eigene Fahrer Animation unterstützt.

BENZINVERBRAUCH:
- Das Auto verbaucht je nach Fahrtgeschwindigkeit unterschiedlich Benzin.  Dafür habe ich euch ein Tankstellenscript mit erstellt.
  Der Sprittank sollte der Fahrzeuggröße angepasst sein. Für ein normales Auto hat sich als "vollertank" 4000 bewährt was 80L entspricht.
  Die initiale Tankfüllung nach Scriptreset wird in "benzintank" festgelegt. Das habe ich auf 2000 eingestellt was 40L entspricht.


LICHT:
- es gibt Unterstützung für 2 Bremslichter/Rücklichter.
- es gibt Unterstützung für 2 Frontscheinwerfer.
- es gibt Unterstützung für einen optionalen Lichtkegel vor dem Fahrzeug zur Strassenbeleuchtung.
- die Einstellung der Paramater wird halbautomatisch unterstützt:
- das Script sucht sich selber die Linknummern heraus wenn ihr die entsprechenden Teile im Mesh folgendermaßen benennt: (auf Gross/Kleinschreibung achten)
"Bremslicht1", "Bremslicht2", "Scheinwerfer1", "Scheinwerfer2", "Lichtkegel", "Hinterrad".

Die zugehörigen Faces müsst ihr aber per Hand eintragen:
für Bremslicht in"bremslichtface" damit im Mesh die richtige Fläche leuchtet, und für Scheinwerfer in "frontlichtface".



Code:
// P319 PKW Script für Simcrossing in Opensim 09 by Tron
// Stand 24.08.2022  V3.01
// unterstützt Hinterraddrift im Sportwagen Modus,
// verbaucht Benzin und zeigt Fahrwerte an im Racemodus
// Gangschaltung mit Leerlauf
// Partikel Textur auf PRIM1 (Fahrzeugprim) vorladen damit diese sofort angezeigt wird
// V3.0.1: Änderung der Funktion Tankanzeige da es (nur) in Opensim 0.9.2.1 einen Division durch 0 Fehler gab wenn Getriebeliste als Parameter eine 0 enthält.

// Version 3.0 enthält Berechtigung Check. Festlegen wer rein darf: Der Besitzer darf immer.
// zusätzlich Personenbezogene Berechtigung anhand der AVA UUID
list    zugangsliste = ["b6a520ac-a468-4bc3-9e52-b509e88a8bce","18da7264-3260-4b63-8173-2a6fd7e93e33"]; // UUIDS berechtigter AVAs

// Öffentlicher Zugang erlaubt?
integer publicaccess = FALSE;   // Darf jeder das Fahrzeug nutzen? [TRUE/FALSE]

// GRUPPENZUGANG erwünscht?
integer groupaccess = TRUE;     // Dürfen Mitglieder der selben Gruppe das Fahrzeug nutzen? [TRUE/FALSE]



//==== FAHRZEUG CHARAKTERISTIKA VARIABLEN: ====


// MOTOR
float   bremskraft           = 6;                                                         // Kraft der Betriebsbremse. Größer bremst stärker
float   motorbremse          = 2.0;                                                       // Motorbremswirkung 1.0 gut, 2.0 weniger Bremswirkung für längerere Auslauf
list    getriebeliste        = [ -5 , 0.001, 15, 25, 35, 50, 70 ];                        // Maximalkraft & Geschwindigkeit des Motors je Gang [ -5 , 0, 15, 25, 35, 55, 70 ];
list    beschleunigungsListe = [1.0, 100.0 , 2.0, 4.0, 8.0, 14.0, 20.0];                  // Beschleunigungsdauer des Motors bis maximaler Ganggeschwindigkeit. 1 = schnell [1.0, 100.0 , 1.0, 3.0, 6.0, 10.0, 15.0];
list    lenkradiusliste      = [ 4, 4, 4, 4, 4, 4, 3 ];                                   // Wenderadius. Größere Werte ermöglichen kleinerer Wendekreise. Gut 4-5 [ 4, 4, 4, 4, 5, 5, 5 ];
list    ganganimationListe   = ["drive","drive","drive","drive","drive","drive","drive"]; // unterschiedliche Animationen je Gang
list    gangListe            = ["Rückwärts","Leerlauf","1. Gang","2. Gang","3. Gang","4. Gang","5. Gang"]; // Bezeichnung der Gänge


// LENKUNG
float   lenkansprechverhalten = 0.4;    // 0.32 REAKTIONSZEIT der LENKUNG 0.2 knackig, 0.3 medium, 0,4träge
float   lenkberuhgungszeit = 0.5;       // 0.80 NACHWIRKZEIT der LENKUNG  0.2++ sehr direkt // 0.5 gut // 1.2 träge
float   lenkradius;

integer racemode = TRUE;                // Zeigt Geschwindigkeit und Benzin an, und verbraucht Benzin
integer sportwagen = FALSE;             // Erlaubt Hinterrad Drift und anderes Fahrverhalten. Nicht für Stadtautos

vector  sitzposition = <1.05,0.45,1.05>;// Sitzposition <0.65,0.25,0.95>

// Linknummern des FAHRZEUGS werden automatisch ermittelt anhand LINKNAMEN. Faces manuell eingetragen
integer bremslichtlink;                 // Bremslicht 1
integer bremslichtlink2;                // Bremslicht 2
integer bremslichtface = 1;             // Face des Bremslichtes

integer frontlichtlink;                 // Frontscheinwerfers 1
integer frontlichtlink2;                // Frontscheinwerfers 2
integer frontlichtface = 2;             // Face des Frontscheinwerfer manuell eintragen
integer lichtkegellink;                 // Lichtkegelprims vor dem Bike
integer hinterradlink;                  // Hinterrades für Rauch
integer lenkradlink;                    // Lenkrad

// TANKDIMENSIONIERUNG
float   vollertank  = 4000;             // Voller Tank
float   benzintank  = 2000;             // Initiale Tankfüllung
integer benzin;

//==== ENDE FAHRZEUG CHARAKTERISTIKA VARIABLEN ====
integer debug = FALSE;                  // DEBUGMODUS zur Fehlersuche und Entwicklung

// TANKEN
integer  listenhandle;                  // für Tanken
integer  channel = -1000;               // Fernbedienungs Kanal für Tankstelle

// GLOBALE VARIABLEN
key      biker;
integer  access;
integer  bikefahrt;
integer  gang;                          // aktuell eingelegter Gang
float    antriebskraft;
integer  ganganzahl;
string   gangname;
string   animation;                     // aktuell gespielte Animation

vector   vel;
float    fahrtgeschwindigkeit;          // aktuelle Geschwindigkeit
float    fahrfaktor;                    // Hilfsvariable zur Rechenreduktion

integer  rechtslenk;
integer  linkslenk;
integer  bremslicht_ist_an;             // aktueller Zustand


// RAUCH
integer rauchpartikelzahl = 1;          // Anzahl Partikel pro Ausstoß und Prim
integer raddrift;                       // aktueller Zustand
list    particle_parameters;

//==== E N D   G L O B A L   V A R I A B L E   D E C L A R A T I O N ====

// Ermitteln der aktuellen Linknummer anhand des Linknamens
integer getlink(string linkname)
{
    integer linknummer = llGetNumberOfPrims();
    do
    {   
        if (linkname == llGetLinkName(linknummer)) { return (linknummer);}
        linknummer--;
    }
    while (linknummer > 0);
    return (0);
}


integer berechtigungscheck(string clicker)  // Funktion um Zugangsberechtigung auszuwerten
{
    integer zugang = FALSE;
    if (clicker == "") { llSay(0,"ungültige USER UUID übergeben"); return zugang;}

    if (publicaccess) { zugang = TRUE; if(debug)llSay(0,"Publiczugang erteilt"); return zugang;}                                 // Öffentlicher Zugang
   
    if (groupaccess) { if(llSameGroup( clicker)) { zugang = TRUE;  if(debug)llSay(0,"Gruppenzugang erteilt"); return zugang;} }   // Gruppenzugang
   
    if (clicker == llGetOwner()) { zugang = TRUE;   if(debug)llSay(0,"Ownerzugang erteilt"); return zugang;}                 // Besitzer Zugang immer erlaubt
   
    integer uuidzugang = llGetListLength(zugangsliste);      // Anzahl der persönlich berechtigten AVAs ermitteln
    if (uuidzugang)                                     // Persönlicher Zugang über UUID Liste
    {
        string personal;
        do
        {
            personal = llList2String(zugangsliste, uuidzugang -1 );
            if( clicker ==  personal) { zugang = TRUE;  if(debug)llSay(0,"UUIDzugang erteilt"); return zugang;}
            uuidzugang--;
        }
        while (uuidzugang);
    }
    return zugang;
}


rauchpartikel()                         // Rauchpartikel Vorab initialisieren um in der Fahrschleife Zeit zu sparen
{
    particle_parameters =
        [         
           PSYS_SRC_TEXTURE, llGetInventoryName(INVENTORY_TEXTURE, 0),  // erste Textur aus Prim auslesen und nehmen
           PSYS_PART_START_SCALE,  <3.0000,3.00000,3.00000>,
           PSYS_PART_END_SCALE, <7.5,7.5,7.5>,
           PSYS_PART_START_COLOR, <0.2 , 0.2 ,0.2 >,
           PSYS_PART_END_COLOR, <0.4,0.4,0.4>,
           PSYS_PART_START_ALPHA, 0.75,
           PSYS_PART_END_ALPHA, 0.0,
           PSYS_SRC_BURST_PART_COUNT, rauchpartikelzahl,
           PSYS_SRC_BURST_RATE, 0.1, //0.3
           PSYS_PART_MAX_AGE, 2.0,
           PSYS_SRC_MAX_AGE,(float) 0.0,
           PSYS_SRC_PATTERN, 2,
           PSYS_SRC_BURST_SPEED_MIN, 1.0,
           PSYS_SRC_BURST_SPEED_MAX, 2.05,
           PSYS_SRC_BURST_RADIUS, 0.1,
           PSYS_SRC_ANGLE_BEGIN, (float) 0.08*PI,
           PSYS_SRC_ANGLE_END, (float) 0.08*PI,
           PSYS_SRC_ACCEL, <2,0,-.3>,
           PSYS_PART_FLAGS, (integer)( 0 | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_EMISSIVE_MASK )
         ];
}


hinterraddrift(integer raddriftenlassen)            // Durchdrehendes Hinterrad: Rauch Erzeugung und Fahrwerte ändern: an / aus
{
    raddrift = raddriftenlassen;
    if (raddrift)
    {
        llMessageLinked(LINK_SET, 10, "2", NULL_KEY);
        llLinkParticleSystem(hinterradlink, particle_parameters );
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,0.1);   // SPURTREUE: starkes seitliches Driften des Hinterrades 0.2
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 40.00); // DRIFTZEIT: starkes Nachdriften des durchdrehenden Hinterrades 10.0
        lenkradius = 8;
    }
    else
    {
        llMessageLinked(LINK_SET, 10, "1", NULL_KEY);
        llLinkParticleSystem(hinterradlink, []);
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,1.0);  // SPURTREUE: kein seitliches Driften des Hinterrades 1.0
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 1.0);  // DRIFTZEIT: wenig Nachdriften des Hinterrades 1.0
        lenkradius = llList2Float(lenkradiusliste, gang);
    }
}


frontlicht(integer an)                     // Schaltet Frontlicht an oder aus
{
    // PRIM_POINT_LIGHT, TRUE, primcolor, fIntensity, fRadius, fFalloff ]
    if (an)
    {  
        llSetLinkPrimitiveParamsFast(frontlichtlink, [PRIM_GLOW, frontlichtface, 1.0]);
        llSetLinkPrimitiveParamsFast(frontlichtlink2, [PRIM_GLOW, frontlichtface, 1.0]);
        llSetLinkPrimitiveParamsFast(lichtkegellink, [PRIM_POINT_LIGHT, TRUE, <1.0, 1.0, 1.0>, 1.0, 10.0, 0.20, PRIM_GLOW, ALL_SIDES, 0.05]);
        llSetLinkPrimitiveParamsFast(bremslichtlink, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.5]);
        llSetLinkPrimitiveParamsFast(bremslichtlink2, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.5]);
    }
    else
    {
        llSetLinkPrimitiveParamsFast(frontlichtlink, [PRIM_GLOW, frontlichtface, 0.0]);
        llSetLinkPrimitiveParamsFast(frontlichtlink2, [PRIM_GLOW, frontlichtface, 0.0]);
        llSetLinkPrimitiveParamsFast(lichtkegellink, [PRIM_POINT_LIGHT, FALSE, <0.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, ALL_SIDES, 0.0]);
        llSetLinkPrimitiveParamsFast(bremslichtlink, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.0]);
        llSetLinkPrimitiveParamsFast(bremslichtlink2, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.0]);
    }
}


bremslicht(integer bremse)                // Schaltet Bremslicht an oder aus
{
    if (bremse)
        {
            llSetLinkPrimitiveParamsFast(bremslichtlink, [PRIM_POINT_LIGHT, TRUE, <1.0, 0.0, 0.0>, 1.0, 2.0, 0.5 , PRIM_GLOW, bremslichtface, 1.0]);
            llSetLinkPrimitiveParamsFast(bremslichtlink2, [PRIM_POINT_LIGHT, TRUE, <1.0, 0.0, 0.0>, 1.0, 2.0, 0.5 , PRIM_GLOW, bremslichtface, 1.0]);
        }
    else
        {
            llSetLinkPrimitiveParamsFast(bremslichtlink, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.5]);
            llSetLinkPrimitiveParamsFast(bremslichtlink2, [PRIM_POINT_LIGHT, FALSE, <1.0, 0.0, 0.0>, 0.0, 0.0, 0.0, PRIM_GLOW, bremslichtface, 0.5]);
        }
    bremslicht_ist_an = bremse;
}


integer tankanzeige(integer funktion )
{
    if (funktion == 1)
    {
        string kmh = (string)llRound(fahrtgeschwindigkeit * 6);
        float drehzahl = llList2Float(getriebeliste, gang );
    if (drehzahl == 0)  drehzahl = 0.001;
        string rpm = (string)llRound(((fahrtgeschwindigkeit / drehzahl)*7000)+700);
        if(gang < 2) rpm = "700";
        string liter = (string) llRound((benzintank / 50));
       
        if (benzintank < ( vollertank * 0.15))
            {
                if(benzintank > 0) { llSetText( kmh + " kmh \n Gang: "+ gangname + " rpm: "+ rpm +  "  \n Benzin: RESERVE " + liter +" Liter",<1,0,0>,1.0); return(TRUE);}
                else { benzintank = 0;  antriebskraft = 0; llSetText( kmh + " kmh \n Gang: "+ gangname + " rpm: 0  \n Benzin: TANK LEER " ,<1,0,0>,1.0); return(FALSE);}
            }
        else { llSetText( kmh + " kmh \n Gang: "+ gangname + " rpm: "+ rpm +  "  \n Benzin: " + liter +" Liter",<1,1,1>,1.0); return(TRUE);}
    }
    else {llSetText("",<0,0,0>,0.0); return(TRUE);}
}

init_engine()                            // Vorinitialisierung des Bikes
{
    bikefahrt = FALSE;
    ganganzahl = llGetListLength(getriebeliste);
    llSetSitText("Fahrer");
    llSitTarget(sitzposition, ZERO_ROTATION);
    llSetLinkPrimitiveParamsFast(LINK_ALL_CHILDREN, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]);
    // LINKNummern ermitteln anhand Namen der Links
    bremslichtlink = getlink("Bremslicht1");
    bremslichtlink2 = getlink("Bremslicht2");
    frontlichtlink = getlink("Scheinwerfer1");
    frontlichtlink2 = getlink("Scheinwerfer2");
    lichtkegellink = getlink("Lichtkegel");   // Lichtkegelprims vor Fahrzeug
    hinterradlink  = getlink("Hinterrad");
    lenkradlink    = getlink("Lenkrad");
}


gangschaltung(string schalte)            // Gangumschaltung
{   
    string neueanimation;

    if (schalte == "Leerlauf") { gang = 1; llMessageLinked(LINK_SET, 10, "0", NULL_KEY); llMessageLinked(LINK_SET, 20, (string)0, NULL_KEY);} // in Leerlauf schalten
    else if (schalte == "Rückwärts") { gang = 0; llSleep(0.5); init_fahrercam(-45.0, 6.0); llMessageLinked(LINK_SET, 10, "-1", NULL_KEY); } // Rückwärts Gang einlegen
    else if (schalte == "Vorwärts") { gang = 2;  llSleep(0.5); init_fahrercam(0.0, 2.5); llMessageLinked(LINK_SET, 10, "1", NULL_KEY);}  // in 1. Gang schalten
    else if (schalte == "+") { gang += 1;}  // in höheren Gang schalten
    else { gang -= 1;}    // schalte in niedrigeren Gang

    lenkradius = llList2Float(lenkradiusliste, gang);
    antriebskraft = llList2Float(getriebeliste, gang);
    float drehmoment = llList2Float(beschleunigungsListe, gang);

    llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, drehmoment);
   
    neueanimation = llList2String(ganganimationListe, gang);
    gangname =  llList2String(gangListe , gang);
    if(racemode) {benzin = tankanzeige(1);}
   
    hinterraddrift(FALSE);
    if (neueanimation != animation) // Animationswechsel
        {
            llStopAnimation(animation);
            animation = neueanimation;
            llStartAnimation(animation);
        }
    if (gang == 1){ llSetTimerEvent(0.0);} else llSetTimerEvent(1.0);
}


// *** KAMERA EINSTELLEN
init_fahrercam(float angle, float distance)
{
    llSetCameraParams(
        [
            CAMERA_ACTIVE, 1,                 // 0=INACTIVE  1=ACTIVE
                CAMERA_BEHINDNESS_ANGLE, angle,   // (0 to 180) DEGREES
                CAMERA_BEHINDNESS_LAG, 1.3,       // (0 to 3) SECONDS  0.3
                CAMERA_DISTANCE, distance,        // ( 0.5 to 10) METERS 2.5
                CAMERA_PITCH, 12.0,               // (-45 to 80) DEGREES
                CAMERA_POSITION_LOCKED, FALSE,    // (TRUE or FALSE)
                CAMERA_POSITION_LAG, 0.25,        // (0 to 3) SECONDS 0.05
                CAMERA_POSITION_THRESHOLD, 0.0,   // (0 to 4) METERS
                CAMERA_FOCUS_LOCKED, FALSE,       // (TRUE or FALSE)
                CAMERA_FOCUS_LAG, 0.0,            // (0 to 3) SECONDS
                CAMERA_FOCUS_THRESHOLD, 0.0,      // (0 to 4) METERS
                CAMERA_FOCUS_OFFSET, <0, 0, 0>    //  METERS
        ]);
    llForceMouselook(FALSE);
}


set_engine()
{
        llSetVehicleType(VEHICLE_TYPE_CAR);
   
// default rotation of prim
        llSetVehicleRotationParam(VEHICLE_REFERENCE_FRAME, <0.00, 0.00, 0.00, 1.00>);
       
// VEHICLE FLAGS  
        llSetVehicleFlags(  VEHICLE_FLAG_NO_DEFLECTION_UP | VEHICLE_FLAG_LIMIT_ROLL_ONLY | VEHICLE_FLAG_HOVER_UP_ONLY | VEHICLE_FLAG_LIMIT_MOTOR_UP);

// LINEAR MOTOR ANTRIEB UND SPURTREUE
        llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 1.0);                // 1.0 BESCHLEUNIGUNG des MOTORS: Wirkung: Größere Zahl ergibt geringere Beschleunigung. 10 Gut für hohen Gang
        llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, motorbremse);  // 2.0 MOTORBREMSE: Wirkung: Kleinere Zahl größere Motorbremswirkung
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,1.0);            // 1.0 SPURTREUE: bewirkt starkes seitliches driften des Hinterrades. 0.2 driftet stark für Start mit drehenden rauchenden Reifen, 0.5 leichtes driften. 1 fährt Spurtreu
        llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 1.00);            // 1.0 DRIFTZEIT nach Lenkstop: Kleine Zahl kurzes Nachdriften [1, .. , 100 ] Griffigkeit der Strasse simulierbar. 1trockener Asphalt, 100 Eis. 10 für Start mit drehenden rauchenden Reifen,

// ANGULAR MOTOR LENKUNG
        llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, lenkansprechverhalten);     // REAKTIONSZEIT der LENKUNG
        llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, lenkberuhgungszeit);  // NACHLENKZEIT bis GERADEAUSLAUF
        llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 1.00);                  // 1.0 SPURTREUE  wird dynamisch eingestellt
        llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 1.00);                  // 1.00 DRIFTZEIT

// Friction Reibung
        llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE,  <1.0,1.0,1.0>  ); // ohne sichtbare Auswirkung
        llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <1.0,1.0,1.0> );  // ohne sichtbare Auswirkung

// Vertical Attraction Vertikale Zugkraft
        llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 1.0);  // 1.0 wichtig
        llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 5.00);

// BANKING Nachschieben vermutlich ohne Wirkung
    llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.0 );
    llSetVehicleFloatParam(VEHICLE_HOVER_TIMESCALE, 0.0 );
    llSetVehicleFloatParam(VEHICLE_HOVER_HEIGHT, 0.0 );
    llSetVehicleFloatParam(VEHICLE_BUOYANCY, 0.0 );
    llCollisionSound("", 0.0);
}


default
{
    state_entry()
    {
        if(!debug) llSetLinkTexture(LINK_THIS,llGetInventoryName(INVENTORY_TEXTURE, 0), ALL_SIDES);  // Partikeltextur auf roortprim vorladen damit sie sofort angezeigt wird
        init_engine();
        rauchpartikel();
        llSetText("",<0,0,0>,0.0);
        state Fahrbereit;
    }
   
    on_rez(integer param) { llResetScript();}
}


state Fahrbereit
{
    state_entry() {}


    on_rez(integer param) { llResetScript();}


    changed(integer change)
    {
        if ((change & CHANGED_LINK) == CHANGED_LINK)
        {
            biker = llAvatarOnSitTarget();    // wir haben einen Fahrer
            if (biker != NULL_KEY)
                {
                    access = berechtigungscheck(biker);        // Funktion für Berechtigungs Check aufrufen
                    if(access) {llRequestPermissions(biker, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS | PERMISSION_CONTROL_CAMERA | PERMISSION_TRACK_CAMERA);}
                    else
                    {
                        llInstantMessage(biker, "Sorry du hast keine Erlaubnis dieses Fahrzeug zu nutzen");
                        llPushObject(biker, <3,3,21>, ZERO_VECTOR, FALSE);
                    }
                }         
            else
                {   // Fahrer ist aufgestanden
                llMessageLinked(LINK_SET, 10, "0", NULL_KEY);  // Räder stoppen
                llSetTimerEvent(0.0);
                llSetStatus(STATUS_PHYSICS, FALSE);
                bremslicht(FALSE);                 // Bremslicht ausschalten
                frontlicht(FALSE);
                bikefahrt = FALSE;
                llStopAnimation(animation);
                hinterraddrift(FALSE);
                llPushObject(biker, <3,3,21>, ZERO_VECTOR, FALSE);
                llReleaseControls();
                llClearCameraParams();
                llSetCameraParams([CAMERA_ACTIVE, 0]);
                benzin = tankanzeige(FALSE);
               // llResetScript(); // Hinderlich bei Benzinberechnung. Ansonsten gut
                llListenRemove(listenhandle);
                state default;
            }
        }
    }

    run_time_permissions(integer perm)
    {
        if (perm)
        {
            set_engine();                // MOTOR einstellen
            listenhandle = llListen(channel,"","","");
            llSetStatus(STATUS_PHYSICS | STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE);
            frontlicht(TRUE);
            bikefahrt = TRUE;           // BIKE fährt
            animation = "sit";
            gangschaltung("Leerlauf"); // im Leerlauf starten und Animation ändern
           // if(racemode) benzin = tankanzeige(TRUE);
            init_fahrercam(0.0, 2.5);
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
            llSleep(1.5);
        }
    }


    control(key id, integer tastenzustand, integer tastenaenderung)
    {
        if(!bikefahrt){return;}
        vector AngularMotor;
       
        integer tastefrischgedrueckt = tastenzustand & tastenaenderung;   
        integer tastelosgelassen = ~tastenzustand & tastenaenderung;
     //     integer tastegehalten = tastenzustand & ~tastenaenderung;
     //     integer tastenichtgehalten = ~tastenzustand & ~tastenaenderung;

        vel = llGetVel();
        fahrtgeschwindigkeit = llVecMag(vel);            // Geschwindigkeit
        fahrfaktor = fahrtgeschwindigkeit / 20;     // Hilfsvariable zur Rechenreduktion


// in höheren Gang schalten mit BILD AUF
        if(tastefrischgedrueckt & (CONTROL_UP | CONTROL_RIGHT)) { if (gang < (ganganzahl -1)) gangschaltung("+"); llSleep(0.15); return;}
// sonst in niedrigerne Gang schalten mit BILD AB
        else if(tastefrischgedrueckt & (CONTROL_DOWN | CONTROL_LEFT)) { if (gang > 0) gangschaltung("-"); return; }


// weiterhin Vorwärts Gas geben
        if (tastenzustand & CONTROL_FWD)
        {
            if (gang < 2) gangschaltung("Vorwärts");        // Auf 1. Gang schalten wenn kein Vorwärtsgang eingelegt war
            else { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft,0,0>);} // Linear Motor Kraft geben
           
// Sport Gangschaltung aufwärts
            if  ((tastefrischgedrueckt & CONTROL_ROT_RIGHT) && (tastefrischgedrueckt & CONTROL_ROT_LEFT))  { if (gang < (ganganzahl -1)) gangschaltung("+"); tastefrischgedrueckt = FALSE; tastenzustand = FALSE; llSleep(0.1); return; }
// Sport Gangschaltung abwärts
            else if ((tastefrischgedrueckt & CONTROL_BACK)) {if (gang > 2) gangschaltung("-"); tastefrischgedrueckt = FALSE; tastenzustand = FALSE; llSleep(0.1); return; }
      
        }
// sonst Rückwärts schalten (nur wenn kein Gas gegeben wird, und Fahrzeug fast im Stillstand)
        else if (tastefrischgedrueckt & CONTROL_BACK) { if ((fahrtgeschwindigkeit < 0.5 ) && (gang > 0)) { gangschaltung("Rückwärts");}}

// weiterhin Rückwärts fahren oder Bremsen
        if (tastenzustand & CONTROL_BACK)
        {
            if (gang > 1)
            {
                if (!bremslicht_ist_an) bremslicht(TRUE);
                if(fahrtgeschwindigkeit > 9) {llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <-bremskraft, 0, 0>);} // stark Bremsen
                else llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0>);  // sanft Bremsen, Rückwärts fahren verhindern
            }
            else if (gang == 0) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft, 0, 0>);} // Rückwärts fahren
        }
// sonst Bremse lösen
        else if (tastelosgelassen & CONTROL_BACK){ if (bremslicht_ist_an) bremslicht(FALSE); llMessageLinked(LINK_SET, 20, (string)fahrtgeschwindigkeit, NULL_KEY);}

// RECHTS lenken
        if  (tastenzustand & CONTROL_ROT_RIGHT)
        {
           if(rechtslenk ==0) llMessageLinked(LINK_SET, 30, (string)1, NULL_KEY);
           if( gang > 1)
            {
                rechtslenk++;
                if(fahrtgeschwindigkeit < 1.0) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <3.0, 0, 0>); // Vortrieb falls zu langsam für Kurvenfahrt
                if(sportwagen) {if ((rechtslenk > 30) & (gang == 2) & (fahrtgeschwindigkeit > 4.5)) { if (!raddrift) hinterraddrift(TRUE);}}     // Hinterrad rotieren lassen
            }
            if(gang >0) AngularMotor.z -= ( lenkradius - fahrfaktor );            // Lenkung wird mit steigender Geschwindigkeit wirkungsloser
            else if(!gang) { AngularMotor.z += 4;}         // Rueckwärts invers lenken
        }
// Nicht mehr rechts lenken
        else if (tastelosgelassen & CONTROL_ROT_RIGHT){ rechtslenk = 0; llMessageLinked(LINK_SET, 30, (string)0, NULL_KEY);}

// LINKS Lenken
        else if (tastenzustand & CONTROL_ROT_LEFT)
        {
           if(linkslenk ==0) llMessageLinked(LINK_SET, 30, (string) (-1), NULL_KEY);
           if( gang > 1)
            {
                linkslenk++;
                if(fahrtgeschwindigkeit < 1.0) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <3.0, 0, 0>); // Vortrieb falls zu langsam für Kurvenfahrt
                if(sportwagen) {if ((linkslenk > 30) & (gang == 2) & (fahrtgeschwindigkeit > 4.5)) { if (!raddrift) hinterraddrift(TRUE);}}      // Hinterrad rotieren lassen
            }        
            if(gang >0) AngularMotor.z += ( lenkradius - fahrfaktor );            // Lenkung wird mit steigender Geschwindigkeit wirkungsloser
            else if(!gang) { AngularMotor.z -= 4;}          // Rueckwärts invers lenken und Nase kompensieren
        }
// Nicht mehr links lenken
        else if (tastelosgelassen & CONTROL_ROT_LEFT){ linkslenk = 0; llMessageLinked(LINK_SET, 30, (string)0, NULL_KEY);}

        llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, AngularMotor);     // ROTATIONS MOTOR mit Kraft versorgen
        if ((!rechtslenk) & (!linkslenk) & raddrift) {hinterraddrift(FALSE);}        // rauchende Reifen abschalten
    }


    timer()
    {
        vel = llGetVel();
        fahrtgeschwindigkeit = llVecMag(vel);      // beide Richtugnen haben positive Geschwindigkeit!
        fahrfaktor = fahrtgeschwindigkeit / 20;    // Hilfsvariable zur Rechenreduktion
        if(racemode)
        {   
            benzintank -= fahrfaktor;                  // Spritverbrauch
            benzin = tankanzeige(1);
        }
        if((gang != 1) & (fahrtgeschwindigkeit < 0.1)) { gangschaltung("Leerlauf"); fahrtgeschwindigkeit = 0.0;} // bei Stand in Leerlauf schalten
        llMessageLinked(LINK_SET, 20, (string)fahrtgeschwindigkeit, NULL_KEY);
    }


    listen(integer channel, string name, key id, string message)
    {
        string sender =  llGetSubString( message, 0, 35 );

        if(biker == sender)
        {
            float tankmenge =  ((vollertank - benzintank)/50);
            string befehl =  llGetSubString( message, 36, llStringLength( message ));
            if(befehl == "Tanken")
            {
                if(gang ==1)
                {
                    llWhisper(0, (string)tankmenge + "Liter Super getankt, das macht dann €:" + (string)(tankmenge *1.57));
                    benzintank = vollertank;
                    if(racemode) benzin = tankanzeige(1);
                }
                else {llWhisper(0, "Bitte zum Tanken den Motor abstellen");}
            }
        }  
    }
}



Vorderrad und Hinterrad Script

In Vorder und Hinterrad kommt jeweils folgendes Radscript. Das Radscript dreht das verlinkte Radmesh direkt. Dazu muss die Achse des Rads passen.
Alternativ kann man hier auch die Achse im Script einstellen.   lltargetOmega <x,y,z>



Code:
// Radscript Variante by Tron
integer richtung = 0;
float   speed;

default
{
    state_entry()
    {
        llTargetOmega(<0,1,0>,PI,0.0);
    }

    link_message(integer sender_num,integer kanal,string message,key id)
    {
        if (kanal == 10) { richtung = (integer)(message);}
        else if (kanal == 20) { speed = (float)message * 0.20 *PI;}

        if ((richtung > 0) & (speed > 0.1)) llTargetOmega(<0,3,0>,speed,0.5);
        else if ((richtung < 0) & (speed > 0.1)) llTargetOmega(<0,-3,0>,speed,0.5);
        else { speed = 0; llTargetOmega(<0,0,0>,PI,0.0);}
    }
}




Tankstellen Script:

Das Tankstellenscript dient dem Betanken von mir gescripteter Fahrzeuge.
Das Script kommt in einen transparenten Primwürfel, der Phantom gemacht wird. Dieser soll die Zapfsäule großzügig ummanteln damit ein Klick auf die Zapfsäule das Prim trifft.

Getankt wird indem man auf dem Fahrzeug in Nähe der Zapfsäule sitzt,  den LEERLAUF eingelegt hat, und die Zapfsäule anklickt.
Dann muss man warten bis der Tankvorgang abgeschlossen ist. Nun erhält man eine Meldung wieviel getankt wurde.
Die Zapfsäule ist auch für alle anderen modernen Fahrzeuge meiner Entwicklung zu nutzen. Aktuell sind das Autos. Boote werden folgen.

Die Tankstelle funktioniert aktuell nur interaktiv mit meinen Fahrzeugen. (Stand 8.2022 Auto und Bike)
Wenn jemand seine Fahrzeugscripte in das Tanksystem integrieren will, bitte hier posten für Hilfe, oder aus dem Auto Script herauslesen



Code:
P319 Tankstelle Zapfsäulenscript by Tron V1.0

string ident = "Tanken";
integer channel = -1000;                // Fernbedienungs Kanal zur Kommunikation für Fahrzeuge
key user;                               // ID desjenigen der die Zapfsäule berührt- wird ans Fahrzeug gesendet
integer listenhandle;                   // für Tanken

default
{
    touch_end(integer num_detected)
    {
        user =  llDetectedKey(0);
        llSay (0, "Tankvorgang gestartet... bitte warten");
        listenhandle = llListen((channel+1),"","","");
        llSleep(20.0);
        llWhisper(channel,(string) user +ident);    // ID desjenigen der die Zapfsäule berührt- wird ans Fahrzeug gesendet
    }

    listen(integer channel, string name, key id, string message)
    {
        string sender =  llGetSubString( message, 0, 35 );
        if(user == sender)
        {
            string befehl =  llGetSubString( message, 36, llStringLength( message ));
            {
                llSay(0, befehl);
                llListenRemove(listenhandle);
            }
        }
    }
}




Wie immer wünsche ich viel Spaß, und freue mich auf konstruktive Rückmeldungen.

Das Radscript könnte noch Verbesserungen vertragen, insbesondere Lenken, jedoch ist dafür Mesh mit entsprechden Achsen notwendig.
Es ist halt auch immer ein Zeitfaktor der die Arbeit für Opensim begrenzt. Ich hab jedenfalls für Heute keine Lust mehr am kleinen 13" Laptop in FullHD Buchstaben zu erahnen, und werde mich an den Strand begeben.


Tron
Zitieren
#2
Update auf Version 3.0.1 am 24.08.2022

Ich habe die Funktion Tankanzeige geändert weil es (nur) unter der Opensim Version 0.9.2.1 unter Umständen zu einem Scritpfehler "Division durch Zero" kam. Dieser Fehler entstand wenn man in den Parametern der Getriebeliste eine 0 einfügte. Das Update ist im Original Post erfolgt.

Tron
Zitieren


Gehe zu:


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