Anbei ein Update des obigen Motorrad Scriptes auf Verison 3.01
Hauptänderung ist ein integriertes Berechtigungs System.
Wer das Bike nutzen darf ist nun einstellbar.
- Besitzer darf immer
- Bestimmte Avas anhand ihrer UUID
- Selbe Gruppe
- oder Jeder
Hauptänderung ist ein integriertes Berechtigungs System.
Wer das Bike nutzen darf ist nun einstellbar.
- Besitzer darf immer
- Bestimmte Avas anhand ihrer UUID
- Selbe Gruppe
- oder Jeder
Code:
// P318 Motorrad mit Renngetriebe für Simcrossing in Opensim 09 by Tron
// Stand 24.08.2022 V3.01
// unterstützt Hinterraddrift, Gangschaltung mit Leerlauf
// verbaucht Benzin und zeigt Fahrwerte an im Racemodus
// Partikel Textur vorladen auf Fahrzeugprim, damit diese sofort angezeigt wird
// V3.01 Änderung der Funktion Tankanzeige um Division durch Zero Fehler in 0.9.2.1 zu verhindern.
// 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 = 1.0; // Motorbremswirkung 1.0 gut, 2.0 weniger Bremswirkung für längerere Auslauf
list getriebeliste = [ -5 , 0.001, 15, 25, 35, 45, 55 ]; // Maximalkraft & Geschwindigkeit des Motors je Gang [ -5 , 0, 15, 25, 35, 55, 70 ];
list beschleunigungsListe = [1.0, 100.0 , 1.0, 3.0, 6.0, 10.0, 15.0]; // Beschleunigungsdauer des Motors bis maximaler Ganggeschwindigkeit. 1 = schnell [1.0, 100.0 , 1.0, 3.0, 6.0, 10.0, 15.0];
list ganganimationListe = ["Bikerfahrer","Bikerfahrer","Bikerfahrer","Bikerfahrer","Bikerfahrer","Bikerfahrer","Bikerfahrer"];
list gangListe = ["Rückwärts","Leerlauf","1. Gang","2. Gang","3. Gang","4. Gang","5. Gang"];
// LENKUNG
float lenkansprechverhalten = 0.32; // 0.32 REAKTIONSZEIT der LENKUNG 0.2 knackig, 0.3 medium, 0,4träge
float lenkberuhgungszeit = 0.8; // 0.50 NACHWIRKZEIT der LENKUNG 0.2++ sehr direkt // 0.5 gut // 1.2 träge
float kurvenkraenkung; // 3 - 6 für Motorrad wird dynamisch zugewiesen
float einknicken = 4;
float lenkradius = 4; // Basiswirkung der Lenkung. größere Werte ermöglichen kleinerer Wendekreise. Wirkung wird dynamisch gesteuert: gut 4
integer racemode = TRUE; // Zeigt Geschwindigkeit und Benzin an, und verbraucht Benzin
vector sitzposition = < -0.690, 0.0, 1.65>; // Sitzposition
// Linknummern des FAHRZEUGS werden automatisch ermittelt anhand LINKNAMEN. Faces manuell eingetragen
integer bremslichtlink; // Bremslicht
integer bremslichtface = ALL_SIDES; // Face des Bremslichtes
integer frontlichtlink; // Frontscheinwerfer
integer frontlichtface = 6; // Face des Frontscheinwerfer manuell eintragen
integer lichtkegellink; // Lichtkegelprims vor dem Bike
integer hinterradlink = 5; // Linknummer des Hinterrades für Rauch
// TANKDIMENSIONIERUNG
float vollertank = 600; // Voller Tank
float benzintank = 600; // 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 = 4;
}
}
bikeausrichten(integer park) // Richtet das Bike in Park und Fahr Positionen aus
{
rotation bikerot = llGetRot();
if (park) llSetRot(<-0.4, bikerot.y, bikerot.z, PI>); // Bike parken (<0.0, -0.20, bikerot.z, PI>);
else llSetRot(<0.0, bikerot.y, bikerot.z, PI>); // Bike fahren
}
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(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]);
}
else
{
llSetLinkPrimitiveParamsFast(frontlichtlink, [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]);
}
}
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]);}
else {llSetLinkPrimitiveParamsFast(bremslichtlink, [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 * 5);
float drehzahl = llList2Float(getriebeliste, gang );
if (drehzahl == 0) drehzahl = 0.001;
string rpm = (string)llRound(((fahrtgeschwindigkeit / drehzahl)*7000)+600);
if(gang < 2) rpm = "600";
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("Biker");
llSitTarget(sitzposition, ZERO_ROTATION);
llSetLinkPrimitiveParamsFast(LINK_ALL_CHILDREN, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]);
// LINKNummern ermitteln anhand Namen der Links
bremslichtlink = getlink("Bremslicht");
frontlichtlink = getlink("Scheinwerfer");
lichtkegellink = getlink("Lichtkegel"); // Lichtkegelprims vor Fahrzeug
hinterradlink = getlink("Hinterrad");
}
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
antriebskraft = llList2Float(getriebeliste, gang);
float drehmoment = llList2Float(beschleunigungsListe, gang);
llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, drehmoment);
neueanimation = llList2String(ganganimationListe, gang);
gangname = llList2String(gangListe , gang);
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_LIMIT_MOTOR_UP);
llSetVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP | VEHICLE_FLAG_HOVER_TERRAIN_ONLY); // Fahrzeug Grundausrichtung bei falschen Mesh Axen
// 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 UND NEIGUNG BEI KURVEN
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 <1.0,1.0,0.10>
llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <1.0,1.0,1.0> ); // ohne sichtbare Auswirkung <1.0,1.0,1.0>
// Vertical Attraction Vertikale Zugkraft
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 1.0); // ohne sichtbare Auswirkung 5.5
llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1.00); // 1.0 FINAL sonst säuft Nase in Kurven ab // Werte <= 0.4 ZAPPELT Fahrzeug schlecht! SOLL1
// BANKING Nachschieben
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 1.0 );
llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 0.5 );
llSetVehicleFloatParam( VEHICLE_BANKING_MIX, 1.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
bikeausrichten(TRUE);
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);
bikeausrichten(TRUE);
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,"","","");
bikeausrichten(FALSE);
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
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 /10; // Hilfsvariable zur Rechenreduktion
// in höheren Gang schalten mit BILD AUF
if(tastefrischgedrueckt & (CONTROL_UP | CONTROL_RIGHT)) { if (gang < (ganganzahl -1)) gangschaltung("+");}
// sonst in niedrigerne Gang schalten mit BILD AB
else if(tastefrischgedrueckt & (CONTROL_DOWN | CONTROL_LEFT)) { if (gang > 0) gangschaltung("-");}
// 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
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);}
// Vorderrad Aufsteigen bei Vorwärtsfahrt und links + rechts Pfeiltasten
if ((tastenzustand & CONTROL_ROT_RIGHT) && (tastenzustand & CONTROL_ROT_LEFT))
{
if((gang == 2) || (gang == 3)) // nur im 1. und 2. Gang aufsteigen lassen
{
rechtslenk++; linkslenk++; // eventuell rauchende Reifen erhalten
AngularMotor.y -= ( 2.7 ); // Vorderrad aufsteigen lassen
if(fahrtgeschwindigkeit < 1.0) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <5.0, 0, 0>); // Vortrieb falls zu langsam für Aufsteigen
}
}
// RECHTS lenken
if (tastenzustand & CONTROL_ROT_RIGHT)
{
if( gang > 1) // Einknicken in Kurvenmittelpunkt bei Vorwärtsfahrt
{
rechtslenk++;
// AngularMotor.y -= ( 1.15 ); // Nase hoch zur Kompensation des Eintauchens 0.75
if(fahrtgeschwindigkeit < 1.0) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <3.0, 0, 0>); // Vortrieb falls zu langsam für Kurvenfahrt
if ((rechtslenk > 30) & (gang == 2) & (fahrtgeschwindigkeit > 4.5)) { if (!raddrift) hinterraddrift(TRUE);} // Hinterrad rotieren lassen
}
AngularMotor.y -= ( 1.15 ); // Nase hoch zur Kompensation des Eintauchens 0.75
AngularMotor.x += ( einknicken + fahrfaktor ); // Seitlich einknicken steigt mit Geschwindigkeit (3-6 gut)
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
if (tastenzustand & CONTROL_ROT_LEFT)
{
if( gang > 1) // Einknicken in Kurvenmittelpunkt bei Vorwärtsfahrt
{
linkslenk++;
// AngularMotor.y -= ( 1.15 ); // Nase hoch zur Kompensation des Eintauchens
if(fahrtgeschwindigkeit < 1.0) llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <3.0, 0, 0>); // Vortrieb falls zu langsam für Kurvenfahrt
if ((linkslenk > 30) & (gang == 2) & (fahrtgeschwindigkeit > 4.5)) { if (!raddrift) hinterraddrift(TRUE);} // Hinterrad rotieren lassen
}
AngularMotor.y -= ( 1.15 ); // Nase hoch zur Kompensation des Eintauchens
AngularMotor.x -= ( einknicken + fahrfaktor ); // Seitlich einknicken steigt mit Geschwindigkeit (3-6 gut)
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 links lenken
else if (tastelosgelassen & CONTROL_ROT_LEFT){ linkslenk = 0;}
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!
float verbrauch = fahrtgeschwindigkeit / 20; // Hilfsvariable zur Rechenreduktion
if(racemode)
{
benzintank -= verbrauch; // 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");}
}
}
}
}