Hanggleiter Flugscript für Opensim mit Bullet Physikengine
Das Skript wurde unter opensim 09 mit Bullet Physikengine getestet.
Mit einigen Änderungen der Parameter sollte es auch unter anderen Bedingungen in Opensim laufen.
Für SL Bedarf es größerer Änderungen, vor allem im Berechtigungs System.
Grundlagen von Flugscripten:
- Flugobjekte können Höhe gewinnen und verlieren (Linear Motor ).
- Flugobjekte lenken indem sie seitlich wegdrehen (Angular Motor) und die Nase anheben (Angular Motor ).
- Flugobjekte benötigen eine Startgeschwindigkeit.
Anweisung:
1. Erstellen Sie einen Würfel mit der Größe 4 x 3 x 0,4 m. Dieser dient uns später als Physik RootPrim für die Aufnahme des Scriptes und der Sitzanimation.
Ändern Sie die Prim-Einstellung von "Touch" auf "auf Objekt sitzen".
Das RootPrim darf nicht Phantom sein sonst geht die Physik Engine nicht! Jedoch wird der später verlinkte Mesh Hanggleiter per Script ohne physikalische Form eingestellt, um die Performance zu erhöhen
2. Fügen Sie eine Sitzanimation in dieses Prim ein. Diese muss "sitzanimation" heissen , oder sie ändern den Namen im Script.
Die Einstellung der Sitzposition findet man im Script an dieser Stelle. Sie sollte an das eigenen Flugobjekt angepasst werden.
//==== Globale User Variablen
vector sitzposition = <-0.2, -0.0, -0.12>; // Sitzposition
3. Legen Sie das Skript in das Prim hinein, und resetten es. Nun nehmen Sie Platz. Das Skript macht das Rootprime unsichtbar.
( Verwenden Sie die Steuerung ALT T, um es anzuzeigen. )
Versuchen Sie nun, das Objekt zu fliegen. Der Würfel Box wird als physische Form des Segelflugzeugs verwendet.
Wenn Sie es also für andere Flugobjekte verwenden, müssen Sie die Prims-Größen ändern. Guten Flug!
4. Um ein sichtbares Objekt daran zu linken gehen sie folgendermaßen vor:
Bringen sie das vorhin erstellte Prim auf eine exakte Simposition und exakte Ausrichtung im Winkel.
Den Hanggleiter kann man hier als freies Mesh finden:
https://www.cadnav.com/3d-models/aircraft/
Hinweise zum Flugverhalten:
Das Flugobjekt kennt 2 Gänge: Stehen und Fliegen.
Die Parameter für den Flugmodus findet man in der Scriptsektion "Flugzeug Konstanten"
Der Leerlauf enspricht dabei immer dem ersten Parameter und soll so belassen werden.
der 2. Parameter entspricht dann dem Flugmodus.
// === FLUGZEUG KONSTANTEN =====
list getriebeliste = [ 0, 35]; // Antriebskraft beim Fliegen: hier aktuell 35
list lenkgetriebeListe = [0 , 0.4 ]; // Wendigkeit, höhere Werte sind wendiger. Hier 0.4
float kurvenkraenkung = 5; // Querneigung beim Kurvenflug, hier 5
float abfluggeschwindigkeit = 20.0; // Mindestgeschwindigkeit um Auftrieb zu erhalten. darunter verbleibt man am Boden. Hier 20
Die Bedienung erfolgt mit den Cursortasten sowie Bild AUF/AB
Bild auf- Steigen
Bild ab - Sinken
Corsor auf: beschleunigen und umschalten aus Standmodus in Flugmodus
Cursor ab: Landeanflug einleiten
Cursor links- rechts: lenken
Es gibt einen automatischen Landeanflug der mit der "Pfeil abwärts" Taste ausgelöst wird.
Dieser kann duch drücken der Taste "BILD auf" abgebrochen werden.
Die seitlichen Steuertasten bleiben dabei weiter im Gebrauch.
Bei Flughöhe unter 2 Meter über dem Simboden wird automatisch gelandet und der Standmodus aktiviert.
Das Überfliegen von Simgrenzen in Opensim 0.9x wird unterstützt.
Das Scritp dient insbesondere dem Erlernen des scriptings von physikalischen Fahrzeugen, wie es im Grundlagen Artikel beschrieben wurde.
Dabei ist es neben den Flugrelevanten Teilen noch um ein paar Schmankerl erweitert damit es sofort nutzbar wird.
Parameter
integer racemode = TRUE; // Zeigt Geschwindigkeits Text an. kann mit FALSE abgeschalten werden
Da dieses Script zum Lernen gedacht ist hier eine ERKLÄRUNG der FUNKTIONEN
init_engine()
verwende ich um die Grundinitialisierungen des Flugscriptes gebündelt aufzurufen. Danach ist das Fahrzeug einsatzbereit.
Wird üblicherweise beim Scriptstart aufgerufen- oder bei Verlassen des Fahrzeuges durch den Piloten weil da ein Scriptreset durchgeführt wird.
gangschaltung(string schalte)
stellt die gesamten Flugparameter je nach Gang ein (hier Standmodus / Flugmodus)
Wird während des Fluges aufgerufen.
init_followCam()
stellt die Position ein aus der ihr das Flugzeug beim Fliegen seht.
set_engine()
stellt die Grundparameter der Physikengine ein. Diese Einstellungen sind verantwortlich wie die Linear Motor Steuerwerte und Angular Motor Steuerwerte verarbeitet werden. Diese Einstellungen sind stark abhängig von der eingesetzten Physikengine. Portiert man das Script nach SL (Havoc Physik engine) oder auf eine ander Opensim Physik engine, so sind hier alle Parameter anzupassen.
default
ist (immer) der start der Hauptroutine des Scritpes. diese ruft zuerst "state_entry()" auf
state_entry()
ist die erste Initialisietungs Routine die beim Scriptstart ausgeführt wird.
Diese gibt es je "State"- also duchaus mehrfach.
Ein Status wirkt wie eine große Umklammerung/Kapselung aller darin enthaltenen Routinen.
Wird ein Status verlassen, so wird ales darin laufende hinfällig und gestoppt.
state Ground
ist ein weiter Status. Ich verwende den im Flugmodus.
So lassen sich verschiedene Elemente - wie der Timer und die Tastaturüberprüfung, auf den Flugmodus beschränken.
state_entry()
wieder erste routine die aufgerufen wird-nur diesmal wenn der Status "Ground" gesetzt ist
on_rez(integer param)
prüft ob das Flugobjekt eventuell im flugmodus ins inventar geholt wurde und nun so gerezzt wird. Dann resettet es das Script.
changed(integer change)
if ((change & CHANGED_LINK) == CHANGED_LINK) detektiert ob sich jemand auf das Flugobjekt setzt oder aufsteht, und führt dann die notwendigen Iniitialisierungen durch.
if ((change & CHANGED_REGION) == CHANGED_REGION) detektiert ob es eine Simgrenzen Überquerung gab.
run_time_permissions(integer perm)
Diese Routine wird aufgerufen wenn das Scritp die Berechtigung angefordert hat Tastatur und Kamerasteuerung zu übernehmen.
Dieses Verhalten ist grob unterschiedlich in SL und Opensim! In Opensim ist diese Rechtefreigabe eigentlich nur "pro forma". Keiner schert sich drum ob sie tatsächlich erfolgte. SL ist hier strikt. Die SL Variante der Rechteholung funktioniert aber in Opensim nicht.
control(key id, integer held, integer change)
Dies ist die Hauptroutine der Fahrzeugsteuerung. Hier erfolgt die Auswertugn von Tastendrücken und der Aufruf der Bearbeitungs Funktionen.
Ebenso erfolgt hier der Aufruf des ANGULAR Motors! Deteils sieht in meinem Grundlagen Artikel.
timer()
Hier erfolgt die Periodische Kraft/Impulsversorgung des Linear Motros
Während des Fluges werden also nur 2 Routinen standig ervwendet:
timer um Vekorkräfte zu erzeugen, und Control um rotations Kräfe zu erzeugen.
Entsprechend wichtig ist das diese beiden Routinen so kurz wie möglich gehalten werden damit das Fahrzeug sich dynamisch anfühlt.
Mit Kürze meine ich aber nicht die Zeilen des Programmcodes, sondern die Anzahl und Aufwändigkeit der Berechungen die darin ablaufen.
Dies kann durch vorab Berechnungen von Teil-und Zwischenergebnissen sowie Initialisierungen vorab deutlich minimiert werden.
Viel Spaß beim Testen
Tron
PS falls sich Fehler eingeschlichen haben sollten gebt bitte Bescheid.
Der Hanggleiter kann als Fertigmodell auch bei mir direkt abgeholt werden in Virtual Africa.
Er befindet sich im Beachshop ( Strohhüte ) auf der Isla Bonita.
Link zu Physik Fahrzeuge Grundlagen
https://service-silberwelten.de/showthread.php?tid=68
Das Skript wurde unter opensim 09 mit Bullet Physikengine getestet.
Mit einigen Änderungen der Parameter sollte es auch unter anderen Bedingungen in Opensim laufen.
Für SL Bedarf es größerer Änderungen, vor allem im Berechtigungs System.
Grundlagen von Flugscripten:
- Flugobjekte können Höhe gewinnen und verlieren (Linear Motor ).
- Flugobjekte lenken indem sie seitlich wegdrehen (Angular Motor) und die Nase anheben (Angular Motor ).
- Flugobjekte benötigen eine Startgeschwindigkeit.
Anweisung:
1. Erstellen Sie einen Würfel mit der Größe 4 x 3 x 0,4 m. Dieser dient uns später als Physik RootPrim für die Aufnahme des Scriptes und der Sitzanimation.
Ändern Sie die Prim-Einstellung von "Touch" auf "auf Objekt sitzen".
Das RootPrim darf nicht Phantom sein sonst geht die Physik Engine nicht! Jedoch wird der später verlinkte Mesh Hanggleiter per Script ohne physikalische Form eingestellt, um die Performance zu erhöhen
2. Fügen Sie eine Sitzanimation in dieses Prim ein. Diese muss "sitzanimation" heissen , oder sie ändern den Namen im Script.
Die Einstellung der Sitzposition findet man im Script an dieser Stelle. Sie sollte an das eigenen Flugobjekt angepasst werden.
//==== Globale User Variablen
vector sitzposition = <-0.2, -0.0, -0.12>; // Sitzposition
3. Legen Sie das Skript in das Prim hinein, und resetten es. Nun nehmen Sie Platz. Das Skript macht das Rootprime unsichtbar.
( Verwenden Sie die Steuerung ALT T, um es anzuzeigen. )
Versuchen Sie nun, das Objekt zu fliegen. Der Würfel Box wird als physische Form des Segelflugzeugs verwendet.
Wenn Sie es also für andere Flugobjekte verwenden, müssen Sie die Prims-Größen ändern. Guten Flug!
4. Um ein sichtbares Objekt daran zu linken gehen sie folgendermaßen vor:
Bringen sie das vorhin erstellte Prim auf eine exakte Simposition und exakte Ausrichtung im Winkel.
Den Hanggleiter kann man hier als freies Mesh finden:
https://www.cadnav.com/3d-models/aircraft/
Hinweise zum Flugverhalten:
Das Flugobjekt kennt 2 Gänge: Stehen und Fliegen.
Die Parameter für den Flugmodus findet man in der Scriptsektion "Flugzeug Konstanten"
Der Leerlauf enspricht dabei immer dem ersten Parameter und soll so belassen werden.
der 2. Parameter entspricht dann dem Flugmodus.
// === FLUGZEUG KONSTANTEN =====
list getriebeliste = [ 0, 35]; // Antriebskraft beim Fliegen: hier aktuell 35
list lenkgetriebeListe = [0 , 0.4 ]; // Wendigkeit, höhere Werte sind wendiger. Hier 0.4
float kurvenkraenkung = 5; // Querneigung beim Kurvenflug, hier 5
float abfluggeschwindigkeit = 20.0; // Mindestgeschwindigkeit um Auftrieb zu erhalten. darunter verbleibt man am Boden. Hier 20
Die Bedienung erfolgt mit den Cursortasten sowie Bild AUF/AB
Bild auf- Steigen
Bild ab - Sinken
Corsor auf: beschleunigen und umschalten aus Standmodus in Flugmodus
Cursor ab: Landeanflug einleiten
Cursor links- rechts: lenken
Es gibt einen automatischen Landeanflug der mit der "Pfeil abwärts" Taste ausgelöst wird.
Dieser kann duch drücken der Taste "BILD auf" abgebrochen werden.
Die seitlichen Steuertasten bleiben dabei weiter im Gebrauch.
Bei Flughöhe unter 2 Meter über dem Simboden wird automatisch gelandet und der Standmodus aktiviert.
Das Überfliegen von Simgrenzen in Opensim 0.9x wird unterstützt.
Das Scritp dient insbesondere dem Erlernen des scriptings von physikalischen Fahrzeugen, wie es im Grundlagen Artikel beschrieben wurde.
Dabei ist es neben den Flugrelevanten Teilen noch um ein paar Schmankerl erweitert damit es sofort nutzbar wird.
Parameter
integer racemode = TRUE; // Zeigt Geschwindigkeits Text an. kann mit FALSE abgeschalten werden
Da dieses Script zum Lernen gedacht ist hier eine ERKLÄRUNG der FUNKTIONEN
init_engine()
verwende ich um die Grundinitialisierungen des Flugscriptes gebündelt aufzurufen. Danach ist das Fahrzeug einsatzbereit.
Wird üblicherweise beim Scriptstart aufgerufen- oder bei Verlassen des Fahrzeuges durch den Piloten weil da ein Scriptreset durchgeführt wird.
gangschaltung(string schalte)
stellt die gesamten Flugparameter je nach Gang ein (hier Standmodus / Flugmodus)
Wird während des Fluges aufgerufen.
init_followCam()
stellt die Position ein aus der ihr das Flugzeug beim Fliegen seht.
set_engine()
stellt die Grundparameter der Physikengine ein. Diese Einstellungen sind verantwortlich wie die Linear Motor Steuerwerte und Angular Motor Steuerwerte verarbeitet werden. Diese Einstellungen sind stark abhängig von der eingesetzten Physikengine. Portiert man das Script nach SL (Havoc Physik engine) oder auf eine ander Opensim Physik engine, so sind hier alle Parameter anzupassen.
default
ist (immer) der start der Hauptroutine des Scritpes. diese ruft zuerst "state_entry()" auf
state_entry()
ist die erste Initialisietungs Routine die beim Scriptstart ausgeführt wird.
Diese gibt es je "State"- also duchaus mehrfach.
Ein Status wirkt wie eine große Umklammerung/Kapselung aller darin enthaltenen Routinen.
Wird ein Status verlassen, so wird ales darin laufende hinfällig und gestoppt.
state Ground
ist ein weiter Status. Ich verwende den im Flugmodus.
So lassen sich verschiedene Elemente - wie der Timer und die Tastaturüberprüfung, auf den Flugmodus beschränken.
state_entry()
wieder erste routine die aufgerufen wird-nur diesmal wenn der Status "Ground" gesetzt ist
on_rez(integer param)
prüft ob das Flugobjekt eventuell im flugmodus ins inventar geholt wurde und nun so gerezzt wird. Dann resettet es das Script.
changed(integer change)
if ((change & CHANGED_LINK) == CHANGED_LINK) detektiert ob sich jemand auf das Flugobjekt setzt oder aufsteht, und führt dann die notwendigen Iniitialisierungen durch.
if ((change & CHANGED_REGION) == CHANGED_REGION) detektiert ob es eine Simgrenzen Überquerung gab.
run_time_permissions(integer perm)
Diese Routine wird aufgerufen wenn das Scritp die Berechtigung angefordert hat Tastatur und Kamerasteuerung zu übernehmen.
Dieses Verhalten ist grob unterschiedlich in SL und Opensim! In Opensim ist diese Rechtefreigabe eigentlich nur "pro forma". Keiner schert sich drum ob sie tatsächlich erfolgte. SL ist hier strikt. Die SL Variante der Rechteholung funktioniert aber in Opensim nicht.
control(key id, integer held, integer change)
Dies ist die Hauptroutine der Fahrzeugsteuerung. Hier erfolgt die Auswertugn von Tastendrücken und der Aufruf der Bearbeitungs Funktionen.
Ebenso erfolgt hier der Aufruf des ANGULAR Motors! Deteils sieht in meinem Grundlagen Artikel.
timer()
Hier erfolgt die Periodische Kraft/Impulsversorgung des Linear Motros
Während des Fluges werden also nur 2 Routinen standig ervwendet:
timer um Vekorkräfte zu erzeugen, und Control um rotations Kräfe zu erzeugen.
Entsprechend wichtig ist das diese beiden Routinen so kurz wie möglich gehalten werden damit das Fahrzeug sich dynamisch anfühlt.
Mit Kürze meine ich aber nicht die Zeilen des Programmcodes, sondern die Anzahl und Aufwändigkeit der Berechungen die darin ablaufen.
Dies kann durch vorab Berechnungen von Teil-und Zwischenergebnissen sowie Initialisierungen vorab deutlich minimiert werden.
Viel Spaß beim Testen
Tron
PS falls sich Fehler eingeschlichen haben sollten gebt bitte Bescheid.
Der Hanggleiter kann als Fertigmodell auch bei mir direkt abgeholt werden in Virtual Africa.
Er befindet sich im Beachshop ( Strohhüte ) auf der Isla Bonita.
Link zu Physik Fahrzeuge Grundlagen
https://service-silberwelten.de/showthread.php?tid=68
Code:
// P315 Release V1 Hang glider Script für Simcrossing in Opensim 09
// by Tron MCP
// Version 1.0 Stand 29.06.2019
// Creative Commons Version
// feel free to use for your builds.
// The Scritp itself has to stay free of costs and fullperm. The header has to be left unchanged.
//==== Globale User Variablen die ohne Multiposer benötigt werden ====
integer debug = FALSE; // Debug Modus
integer racemode = TRUE; // Zeigt Geschwindigkeits Text an
string sitzanimation; // FahrerAnimation
vector sitzposition = <-0.2, -0.0, -0.12>; // Sitzposition
// === FLUGZEUG KONSTANTEN =====
list getriebeliste = [ 0, 35]; // Antriebskraft je Gang
list auftriebsliste = [ 0 , 1]; // Auftrieb je Gang
list lenkgetriebeListe = [0 , 0.4 ]; // Wendigkeit, höhere Werte sind wendiger
list gangListe = ["Leerlauf", "Flugmodus"];
float kurvenkraenkung = 5;
float abfluggeschwindigkeit = 20.0; // Mindestgeschwindigkeit um Auftrieb zu erhalten
vector vel;
float fahrtgeschwindigkeit; // aktuelle Fluggeschwindigkeit
//==== SONSTIGE GLOBAL VARIABLEN ====
float wasserstand;
key pilot;
integer imflug;
integer gang; // aktuell eingelegter Gang
float antriebskraft;
float steigfaehigkeit;
float lenkansprechverhalten;
integer ganganzahl;
string animation; // aktuell gespielte Animation
integer landeanflug;
//==== 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 ====
init_engine()
{
imflug = FALSE;
ganganzahl = llGetListLength(getriebeliste);
llSetSitText("Fliegen");
vector gSitTarget_Rot = llRot2Euler( llGetRootRotation() ); // SIT TARGET in Anhängigkeit von RootPrim Rotation
llSitTarget(sitzposition, llEuler2Rot(DEG_TO_RAD * gSitTarget_Rot));
llSetLinkPrimitiveParamsFast(LINK_ALL_CHILDREN, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]);
llSetLinkAlpha(LINK_THIS, 0.0, ALL_SIDES);
llSetLinkAlpha(LINK_ALL_OTHERS, 1.0, ALL_SIDES);
}
gangschaltung(string schalte)
{
string gangname;
if (schalte == "Flugmodus") { gang = 1;} // in Flugmodus schalten
else { gang = 0;} // in Leerlauf schalten
antriebskraft = llList2Float(getriebeliste, gang);
steigfaehigkeit = llList2Float(auftriebsliste, gang);
lenkansprechverhalten = llList2Float(lenkgetriebeListe, gang);
gangname = llList2String(gangListe , gang);
}
init_followCam()
{
llSetCameraParams([
CAMERA_ACTIVE, 1, // 0=INACTIVE 1=ACTIVE
CAMERA_BEHINDNESS_ANGLE, 2.5, // (0 to 180) DEGREES
CAMERA_BEHINDNESS_LAG, 0.3, // (0 to 3) SECONDS
CAMERA_DISTANCE, 10.0, // ( 0.5 to 10) METERS
CAMERA_PITCH, 12.0, // (-45 to 80) DEGREES
CAMERA_POSITION_LOCKED, FALSE, // (TRUE or FALSE)
CAMERA_POSITION_LAG, 0.0, // (0 to 3) SECONDS
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, <-5, 0, 0> // <-10,-10,-10> to <10,10,10> METERS
]);
llForceMouselook(FALSE);
}
set_engine()
{
//Flugzeug PARAMETER
llSetVehicleType(VEHICLE_TYPE_AIRPLANE);
// linear friction
llSetVehicleVectorParam( VEHICLE_LINEAR_FRICTION_TIMESCALE, <200, 200, 200> );
// angular friction
llSetVehicleFloatParam( VEHICLE_ANGULAR_FRICTION_TIMESCALE, 2 );
// linear motor
llSetVehicleVectorParam( VEHICLE_LINEAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_TIMESCALE, 2 );
llSetVehicleFloatParam( VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, 1.0 );
// agular motor
llSetVehicleVectorParam( VEHICLE_ANGULAR_MOTOR_DIRECTION, <0, 0, 0> );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0 );
llSetVehicleFloatParam( VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 0.4);
// hover
llSetVehicleFloatParam( VEHICLE_HOVER_HEIGHT, 2 );
llSetVehicleFloatParam( VEHICLE_HOVER_EFFICIENCY, 0 );
llSetVehicleFloatParam( VEHICLE_HOVER_TIMESCALE, 3 );
llSetVehicleFloatParam( VEHICLE_BUOYANCY, 0.977 );
// linear deflection
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0 );
llSetVehicleFloatParam( VEHICLE_LINEAR_DEFLECTION_TIMESCALE, 5 );
// angular deflection
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.1);
llSetVehicleFloatParam( VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, 10);
// vertical attractor
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, 1 );
llSetVehicleFloatParam( VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, 1 );
// banking
llSetVehicleFloatParam( VEHICLE_BANKING_EFFICIENCY, 1);
llSetVehicleFloatParam( VEHICLE_BANKING_MIX, .5);
llSetVehicleFloatParam( VEHICLE_BANKING_TIMESCALE, 0.01);
// default rotation of local frame
llSetVehicleRotationParam( VEHICLE_REFERENCE_FRAME, <0,0,0,1>);
// remove these flags
llRemoveVehicleFlags( VEHICLE_FLAG_NO_DEFLECTION_UP
| VEHICLE_FLAG_HOVER_WATER_ONLY
| VEHICLE_FLAG_LIMIT_ROLL_ONLY
| VEHICLE_FLAG_HOVER_TERRAIN_ONLY
| VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT
| VEHICLE_FLAG_HOVER_UP_ONLY
| VEHICLE_FLAG_LIMIT_MOTOR_UP );
}
default
{
state_entry()
{
vector bootposition = llGetPos();
bootposition.z = llGround( ZERO_VECTOR );
wasserstand = llWater( ZERO_VECTOR );
if( bootposition.z < wasserstand ) { bootposition.z = wasserstand;}
llSetRegionPos(bootposition + <0,0,0.1>);
sitzanimation = llGetInventoryName(INVENTORY_ANIMATION, 0);
init_engine();
state Ground;
}
}
state Ground
{
state_entry()
{
llSetText("",<0,0,0>,1.0);
}
on_rez(integer param) { llResetScript();}
changed(integer change)
{
if ((change & CHANGED_LINK) == CHANGED_LINK)
{
pilot = llAvatarOnSitTarget();
if (pilot != NULL_KEY)
{ // wir haben einen Piloten
llSetStatus(STATUS_PHYSICS, TRUE);
llSetStatus(STATUS_ROTATE_Y,TRUE);
llSetStatus(STATUS_ROTATE_Z,TRUE);
llSetStatus(STATUS_ROTATE_X,TRUE);
set_engine();
llRequestPermissions(pilot, PERMISSION_TRIGGER_ANIMATION | PERMISSION_TAKE_CONTROLS | PERMISSION_CONTROL_CAMERA | PERMISSION_TRACK_CAMERA);
llSay(0,"Flieger grüß mir die Sonne!\n\r steuer mit Pfeil vorwärts/links/rechts , \n\r kontrollier die Höhe mit Bild auf/ab \n\r lande mit Pfeil runter.");
imflug = TRUE; // Flugobjekt fliegt
landeanflug = FALSE;
}
else
{ // Pilot hat Flugobjekt verlassen
llSetStatus(STATUS_PHYSICS, FALSE);
imflug = FALSE; // Flugobjekt steht
init_engine();
llStopAnimation( animation ); // entfällt bei Multiposer
llPushObject(pilot, <3,3,21>, ZERO_VECTOR, FALSE);
llReleaseControls();
llClearCameraParams();
llSetCameraParams([CAMERA_ACTIVE, 0]);
if(racemode) { llSetText("",<0,0,0>,1.0); }
llResetScript();
}
}
if ((change & CHANGED_REGION) == CHANGED_REGION)
{
if(debug) llWhisper(0,"Simgrenze überquert");
wasserstand = llWater( ZERO_VECTOR ); // Wasserstand der neuen sim ermitteln
}
}
run_time_permissions(integer perm)
{
if (perm)
{
gangschaltung("Leerlauf"); // im Leerlauf starten
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT, TRUE, FALSE);
init_followCam();
llStopAnimation("sit");
animation = sitzanimation; // aktuelle Animation merken
llStartAnimation(animation);
llSleep(1.5);
}
}
control(key id, integer held, integer change)
{
if(imflug == FALSE) {return;}
vector AngularMotor;
if(racemode) llSetText( (string)fahrtgeschwindigkeit + " kmh",<1,1,1>,1.0);
if(held & CONTROL_UP) // STEIGFLUG gewählt
{
if( fahrtgeschwindigkeit > abfluggeschwindigkeit )
{
landeanflug = FALSE;
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft *0.75, 0, fahrtgeschwindigkeit * steigfaehigkeit>); // STEIGEN
AngularMotor.y = -2.5; // NASE anheben
}
else { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft,0,0>); }
}
else if(held & CONTROL_DOWN) // SINKFLUG gewählt
{
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft *2, 0, - fahrtgeschwindigkeit * steigfaehigkeit>); // SINKEN
AngularMotor.y = 3.5; // NASE runterdrücken
}
else if (held & CONTROL_FWD) // weiterhin Vorwärts Gas gegeben
{ llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft,0,0>); }
if (~held & change & CONTROL_FWD) // Auf Vorwärtsflug geschalten
{
if (gang < 1)
{
gangschaltung("Flugmodus");
llSetTimerEvent(1.0); // gestartet: nun kontinuierlicher Hoehenverlust und Vortrieb zuschalten
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <antriebskraft/2 ,0,0>);
}
}
else if (held & CONTROL_BACK) // Automatisches Landen gewählt
{
if (!landeanflug) llSay(0,"Landung eingeleitet");
landeanflug = TRUE;
AngularMotor.y = 1; // NASE runterdrücken
}
if (held & CONTROL_ROT_RIGHT) // Steuerung nach RECHTS erfolgt
{
if( fahrtgeschwindigkeit > 3 ) // Einknicken in Kurvenmittelpunkt
{
AngularMotor.x += ( lenkansprechverhalten * kurvenkraenkung ); // ROLLEN rechts
AngularMotor.y = AngularMotor.y - ( lenkansprechverhalten * kurvenkraenkung * 0.5); // NASE anheben
}
AngularMotor.z -= lenkansprechverhalten; // RECHTS DREHEN
}
else if (held & CONTROL_ROT_LEFT) // Steuerung nach LINKS erfolgt
{
if( fahrtgeschwindigkeit > 3 ) // Einknicken in Kurvenmittelpunkt
{
AngularMotor.x -= ( lenkansprechverhalten * kurvenkraenkung ); // ROLLEN links
AngularMotor.y = AngularMotor.y - ( lenkansprechverhalten * kurvenkraenkung * 0.5); // NASE anheben
}
AngularMotor.z += lenkansprechverhalten; // LINKS DREHEN
}
llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, AngularMotor);
}
timer()
{
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, < 10 , 0, -8>); // kontinuierlichen Vortrieb von 10 udn Sinken von 8
vel = llGetVel();
fahrtgeschwindigkeit = llVecMag(vel); // Geschwindigkeit ermitteln
vector drachenposition = llGetPos();
float flughoehe = drachenposition.z - llGround( ZERO_VECTOR );
if (flughoehe < 2 ) // automatisch landen
{
llSetTimerEvent(0.0);
llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, < 0,0,0>);
if( drachenposition.z < wasserstand ) { drachenposition.z = wasserstand;}
llSetRegionPos(drachenposition + <0,0,0.1>);
gangschaltung( "Leerlauf");
llSetText("",<0,0,0>,1.0);
}
}
}