Auto Plant Skript - Manfred Aabye - 21.07.2026
Auto Plant 2.27
Automatisches erstellen von Regionen mit Objekten und Texturen.
Automatische Größenerkennung.
Es setzt 4 Terrain PBR Materialien.
Raut die Region leicht auf.
Setzt Bäume, Büsche, Farne, Todholz, Grass und Steine.
PHP-Code: // ============================================================ // OPENSIM WALDPFLANZER SKRIPT MIT DIALOG-MENÜ // ============================================================
// ===== GLOBALE VARIABLEN ===== integer gIntX; integer gIntY; integer gIntZ;
integer gIntStartX; integer gIntStartY; integer gIntEndX; integer gIntEndY;
float gFltPlantProbability; float gFltRandMax;
// ===== START/STOP-FUNKTION ===== integer gIntRunning = FALSE; key gKeyToucher; integer gIntCurrentX; integer gIntCurrentY;
// ===== PFLANZPARAMETER ===== integer PFLANZABSTAND = 6;
// ===== KOMBINIERTE LISTE FÜR ALLE OBJEKTE ===== // Format: [Name, Höhe, Priorität, X-Rotation, Y-Rotation, Z-Rotation, Z-Offset] // Je höher die Priorität, desto wahrscheinlicher wird das Objekt ausgewählt list ALLE_OBJEKTE = [ // Bäume (Priorität 30) "European-Beech-tree-A", 10.0, 30, 0.0, 0.0, 0.0, 0.0, "European-Beech-tree-B", 10.0, 30, 0.0, 0.0, 0.0, 0.0, "European-Oak-tree", 12.0, 30, 0.0, 0.0, 0.0, 0.0, // Büsche (Priorität 25) "Buesche-1", 3.0, 25, 90.0, 0.0, 0.0, -2.00, "Buesche-2", 3.0, 25, 90.0, 0.0, 0.0, -2.00, "Buesche-3", 3.0, 25, 90.0, 0.0, 0.0, -2.00, "Buesche-4", 3.0, 25, 90.0, 0.0, 0.0, -2.00, // Farne (Priorität 20) "Fern-1", 1.2, 20, 90.0, 0.0, 0.0, -0.70, "Fern-2", 1.2, 20, 90.0, 0.0, 0.0, -0.70, "Fern-3", 1.2, 20, 90.0, 0.0, 0.0, -0.70, "Fern-4", 1.2, 20, 90.0, 0.0, 0.0, -0.70, // Todholz (Priorität 15) "Todholz-1", 1.5, 15, 0.0, 0.0, 0.0, -1.30, "Todholz-2", 1.5, 15, 0.0, 0.0, 0.0, -1.30, "Todholz-3", 1.5, 15, 0.0, 0.0, 0.0, -1.30, "Todholz-4", 1.5, 15, 0.0, 0.0, 0.0, -1.30, // Gräser (Priorität 15) "Grass-1", 0.5, 15, 0.0, 0.0, 0.0, -0.10, "Grass-2", 0.5, 15, 0.0, 0.0, 0.0, -0.10, "Grass-3", 0.5, 15, 0.0, 0.0, 0.0, -0.10, "Grass-4", 0.5, 15, 0.0, 0.0, 0.0, -0.10, // Steine (Priorität 10) "Stone-1", 0.8, 10, 0.0, 0.0, 0.0, -0.40, "Stone-2", 0.8, 10, 0.0, 0.0, 0.0, -0.40, "Stone-3", 0.8, 10, 0.0, 0.0, 0.0, -0.40, "Stone-4", 0.8, 10, 0.0, 0.0, 0.0, -0.40 ];
// ===== TERRAIN-TEXTUREN ===== float TextureLow = 10.0; float TextureHigh = 30.0;
key Terrain_Dirt = "1e78c37b-90a1-40d3-a913-31c965309679"; key Terrain_Grass = "a9b4d0d5-5679-4fd5-b9e3-ac4367ea9b95"; key Terrain_Mountain = "795204d3-bd28-467c-b526-08b95090841e"; key Terrain_Rock = "4b012b05-a357-46af-8e6e-e8a9aa501a8c";
// key Terrain_Dirt = "9dc31f61-e30b-44bf-91dc-e4f6a8735407"; // key Terrain_Grass = "16620c30-5efd-451a-ab10-6fb3e69ad59a"; // key Terrain_Mountain = "5abbc6ef-7cb9-4340-9950-6dc61b21c99c"; // key Terrain_Rock = "429726cd-34e4-4bc9-a669-a94f2f69f11e";
// ===== DIALOG-MENÜ VARIABLEN ===== integer MENU_CHANNEL; integer listenHandle; string MENU_TEXT = "\nWähle eine Aktion:"; list MENU_BUTTONS = ["? Pflanzen", "? Terrain", "❌ Schließen"];
// ===== HILFSFUNKTIONEN ===== float getObjectHeight(string objectName) { integer index = llListFindList(ALLE_OBJEKTE, [objectName]); if (index != -1) return llList2Float(ALLE_OBJEKTE, index + 1); return 4.0; // Fallback-Höhe }
float getObjectRotationX(string objectName) { integer index = llListFindList(ALLE_OBJEKTE, [objectName]); if (index != -1) return llList2Float(ALLE_OBJEKTE, index + 3); return 0.0; // Fallback-Rotation }
float getObjectRotationY(string objectName) { integer index = llListFindList(ALLE_OBJEKTE, [objectName]); if (index != -1) return llList2Float(ALLE_OBJEKTE, index + 4); return 0.0; // Fallback-Rotation }
float getObjectRotationZ(string objectName) { integer index = llListFindList(ALLE_OBJEKTE, [objectName]); if (index != -1) return llList2Float(ALLE_OBJEKTE, index + 5); return 0.0; // Fallback-Rotation }
float getObjectZOffset(string objectName) { integer index = llListFindList(ALLE_OBJEKTE, [objectName]); if (index != -1) return llList2Float(ALLE_OBJEKTE, index + 6); return 0.0; // Fallback-Z-Offset }
rotation getRotation(float gradX, float gradY, float gradZ) { return llEuler2Rot(<gradX * DEG_TO_RAD, gradY * DEG_TO_RAD, gradZ * DEG_TO_RAD>); }
// ===== TERRAIN-FUNKTIONEN ===== setTerrain() { list textures = [Terrain_Dirt, Terrain_Grass, Terrain_Mountain, Terrain_Rock]; integer types = 2; osSetTerrainTextures(textures, types); osSetTerrainTexture(0, Terrain_Dirt); osSetTerrainTextureHeight(0, TextureLow, TextureHigh); osSetTerrainTexture(1, Terrain_Grass); osSetTerrainTextureHeight(1, TextureLow, TextureHigh); osSetTerrainTexture(2, Terrain_Mountain); osSetTerrainTextureHeight(2, TextureLow, TextureHigh); osSetTerrainTexture(3, Terrain_Rock); osSetTerrainTextureHeight(3, TextureLow, TextureHigh); llModifyLand(LAND_NOISE, 0); osTerrainFlush(); llOwnerSay("✅ Terrain-Texturen wurden gesetzt und aufgeraut!"); }
// ===== PFLANZEN-FUNKTIONEN ===== plantOneTree() { if (!gIntRunning) return; if (gIntCurrentX >= gIntEndX || gIntCurrentY >= gIntEndY) { gIntRunning = FALSE; llOwnerSay("✅ Pflanzvorgang abgeschlossen!"); llSetText("Fertig - Klicke für neues Menü", <0,1,0>, 1.0); llSetTimerEvent(0.0); return; } gIntX = gIntCurrentX; gIntY = gIntCurrentY; llSetRegionPos(<gIntX, gIntY, gIntZ>); llSetText("X: " + (string)gIntX + " Y: " + (string)gIntY, <1,1,1>, 1.0); // 1. Zufällig entscheiden, ob überhaupt etwas gepflanzt wird float fltDoIRez = llFrand(1.0); if (fltDoIRez >= gFltPlantProbability) { gIntCurrentY += PFLANZABSTAND; if (gIntCurrentY >= gIntEndY) { gIntCurrentY = gIntStartY + (PFLANZABSTAND / 2); gIntCurrentX += PFLANZABSTAND; } return; } // ===== GEWICHTETE AUSWAHL MIT ÜBERSPRINGEN FEHLENDER OBJEKTE ===== // 1. Liste der verfügbaren Objekte erstellen (nur die, die im Inventar sind) list verfuegbareObjekte = []; integer listLength = llGetListLength(ALLE_OBJEKTE) / 7; integer i; for (i = 0; i < listLength; i++) { string objName = llList2String(ALLE_OBJEKTE, i * 7); // Prüfen, ob Objekt im Inventar existiert if (llGetInventoryType(objName) == INVENTORY_OBJECT) { float objHeight = llList2Float(ALLE_OBJEKTE, (i * 7) + 1); integer objPriority = llList2Integer(ALLE_OBJEKTE, (i * 7) + 2); float objRotationX = llList2Float(ALLE_OBJEKTE, (i * 7) + 3); float objRotationY = llList2Float(ALLE_OBJEKTE, (i * 7) + 4); float objRotationZ = llList2Float(ALLE_OBJEKTE, (i * 7) + 5); float objZOffset = llList2Float(ALLE_OBJEKTE, (i * 7) + 6); verfuegbareObjekte += [objName, objHeight, objPriority, objRotationX, objRotationY, objRotationZ, objZOffset]; } // Wenn nicht im Inventar: einfach überspringen } // Falls keine Objekte verfügbar sind if (llGetListLength(verfuegbareObjekte) == 0) { llOwnerSay("⚠️ Keine Objekte im Inventar gefunden!"); gIntRunning = FALSE; llSetTimerEvent(0.0); return; } // 2. Gesamtgewicht der verfügbaren Objekte berechnen integer availableCount = llGetListLength(verfuegbareObjekte) / 7; integer totalWeight = 0; for (i = 0; i < availableCount; i++) { totalWeight += llList2Integer(verfuegbareObjekte, (i * 7) + 2); } // 3. Zufällige Auswahl basierend auf Gewicht integer randomWeight = (integer)llFrand(totalWeight); integer selectedIndex = 0; integer cumulativeWeight = 0; for (i = 0; i < availableCount; i++) { integer priority = llList2Integer(verfuegbareObjekte, (i * 7) + 2); cumulativeWeight += priority; if (randomWeight < cumulativeWeight) { selectedIndex = i; i = availableCount; // Schleife manuell beenden (statt break) } } // 4. Objekt auswählen und pflanzen string gStrObjectName = llList2String(verfuegbareObjekte, selectedIndex * 7); float objectHeight = llList2Float(verfuegbareObjekte, (selectedIndex * 7) + 1); float rotationX = llList2Float(verfuegbareObjekte, (selectedIndex * 7) + 3); float rotationY = llList2Float(verfuegbareObjekte, (selectedIndex * 7) + 4); float rotationZ = llList2Float(verfuegbareObjekte, (selectedIndex * 7) + 5); float zOffset = llList2Float(verfuegbareObjekte, (selectedIndex * 7) + 6); // Position und Rotation setzen vector vecNowPos = llGetPos(); float fltLandHeight = osGetTerrainHeight((integer)vecNowPos.x, (integer)vecNowPos.y); integer intNewX = (integer)vecNowPos.x; integer intNewY = (integer)vecNowPos.y; integer intNewZ = (integer)fltLandHeight; vecNowPos = <intNewX, intNewY, intNewZ>; llSetRegionPos(vecNowPos); // Rotation basierend auf Objekt-Einstellungen rotation objectRotation = getRotation(rotationX, rotationY, rotationZ); // Objekt rezzieren mit Höhenanpassung llRezObject(gStrObjectName, llGetPos() + <0.0, 0.0, objectHeight + zOffset>, <0.0, 0.0, 0.0>, objectRotation, 0); llModifyLand(LAND_NOISE, 0); // Dabei direkt das Terrain aufrauhen. llSleep(0.1); // Debug-Ausgabe (optional - auskommentieren wenn nicht benötigt) // llOwnerSay("? " + gStrObjectName + " | X-Rot: " + (string)rotationX + "° | Y-Rot: " + (string)rotationY + "° | Z-Rot: " + (string)rotationZ + "° | Z-Off: " + (string)zOffset); // Zur nächsten Position gIntCurrentY += PFLANZABSTAND; if (gIntCurrentY >= gIntEndY) { gIntCurrentY = gIntStartY + (PFLANZABSTAND / 2); gIntCurrentX += PFLANZABSTAND; } }
startPlanting() { vector regionSize = osGetRegionSize(); gIntStartX = 0; gIntStartY = 0; gIntEndX = (integer)regionSize.x; gIntEndY = (integer)regionSize.y; gFltPlantProbability = .7; // 70% Wahrscheinlichkeit für Bewuchs gIntZ = 0; gIntRunning = TRUE; gIntCurrentX = gIntStartX + (PFLANZABSTAND / 2); gIntCurrentY = gIntStartY + (PFLANZABSTAND / 2); // Anzahl der verfügbaren Objekte zählen integer availableCount = 0; integer listLength = llGetListLength(ALLE_OBJEKTE) / 7; integer i; for (i = 0; i < listLength; i++) { string objName = llList2String(ALLE_OBJEKTE, i * 7); if (llGetInventoryType(objName) == INVENTORY_OBJECT) availableCount++; } llOwnerSay("? Starte Pflanzvorgang mit " + (string)availableCount + " verfügbaren Objekten..."); llSetText("? Pflanze... Klicke zum Stoppen", <1,1,0>, 1.0); llSetTimerEvent(2.0); }
// ===== HAUPTTEIL DES SKRIPTS ===== default { state_entry() { MENU_CHANNEL = -1 - (integer)("0x" + llGetSubString((string)llGetKey(), -7, -1)); llOwnerSay("? Waldpflanzer bereit. Klicke für Menü."); llSetText("Bereit - Klicke für Menü", <0,1,0>, 1.0); llSetTimerEvent(0.0); } touch_start(integer num_detected) { if (gIntRunning) { gIntRunning = FALSE; llSetTimerEvent(0.0); llListenRemove(listenHandle); llOwnerSay("⏹️ Pflanzvorgang wurde gestoppt!"); llSetText("Gestoppt - Klicke für neues Menü", <1,0,0>, 1.0); return; } key toucher = llDetectedKey(0); llListenRemove(listenHandle); listenHandle = llListen(MENU_CHANNEL, "", toucher, ""); llDialog(toucher, MENU_TEXT, MENU_BUTTONS, MENU_CHANNEL); llSetTimerEvent(60.0); } listen(integer channel, string name, key id, string message) { llSetTimerEvent(0.0); llListenRemove(listenHandle); if (message == "? Pflanzen") { llOwnerSay("? Starte Pflanzvorgang..."); startPlanting(); } else if (message == "? Terrain") { setTerrain(); llDialog(id, "✅ Terrain-Texturen wurden aktualisiert.", ["OK"], MENU_CHANNEL); } else if (message == "❌ Schließen") { llOwnerSay("Menü geschlossen."); } else if (message == "OK") { llOwnerSay("✅ OK."); } } timer() { if (gIntRunning) { plantOneTree(); } else { llSetTimerEvent(0.0); } } }
Fazit: Es wird ein Zufallswald erstellt und ist noch nicht ganz fertig, zur Demo ist das aber schon gut genug.
RE: Auto Plant Skript - Ezry Aldrin - 21.07.2026
Huhu,
klingt extrem interessant, nur wie und wo soll ich das Script starten?, oder kann man etwa inworld einfach so
ein PHP Script starten?
Denn alles einzeln zu machen ist bei Grössen von 1024 oder mehr einfach zuviel Arbeit.
Ich war leider sehr lang inaktiv, wenn also was neues gekommen ist für OS, habe ich das schlicht nicht mitbekommen.
Oder bezieht sich das auf das was du bei den Zollbestimmungen gepostet hast, dann muesste ich nur wissen wie ich das ans laufen bekomme.
lg
Ezry
RE: Auto Plant Skript - Manfred Aabye - 21.07.2026
Das OSSL Skript kommt auf einer Region in einen Würfel und dazu Bäume, Büsche, Farne, Todholz, Grass und Steine sowie die Terraintexturen einfügen.
Anklicken, dann erscheint ein Menü, dort hat man die Auswahl zwischen Pflanzen und Terrain.
Fehlende Bäume, Büsche, Farne, Todholz, Grass und Steine werden ignoriert.
RE: Auto Plant Skript - Ezry Aldrin - 21.07.2026
Huhu
leider bekomme ich die Fehlermeldung
(140,4) Error: undefined constant/function/variable osSetTerrainTextures(list,integer)
Beim click auf den Fehler springt der in diese Zeile
osSetTerrainTextures(textures, types);
Mach ich irgendwas verkehrt? Habe das Script gespeichert und in den Würfel geworfen, dazu Bäume und die Tarraintexturen und mehr nicht
lg
Ezry
RE: Auto Plant Skript - Manfred Aabye - 22.07.2026
Dir fehlen die Materialien und Texturen.
Suche dir 4 Materialien aus deinem Inventar aus.
Rechte Maustaste und kopiere UUID.
Füge diese ins Skript ein.
PHP-Code: ... key Terrain_Dirt = "1e78c37b-90a1-40d3-a913-31c965309679"; key Terrain_Grass = "a9b4d0d5-5679-4fd5-b9e3-ac4367ea9b95"; key Terrain_Mountain = "795204d3-bd28-467c-b526-08b95090841e"; key Terrain_Rock = "4b012b05-a357-46af-8e6e-e8a9aa501a8c"; ...
RE: Auto Plant Skript - Ezry Aldrin - 22.07.2026
Huhu
Habe ich gemacht, der Fehler bleibt der Gleiche, langsam fehlt mir die Idee, die Texturen liegen sogar auf der Region auf und dennoch Fehler
Ich schau Morgen nochmal in Ruhe vielleicht seh ich den Fehler jetzt nicht. Mir wäre das Modul lieber, wenn es ans laufen zu bringen ist, leider jedoch habe ich diese UUIDs nicht die in die C# Datei rein muss, nur die von den Grundtexturen habe ich schon eingetragen. besitze einfach kein trockenes Gras. Einige B#ume habe ich schon aber mit Gras Farn usw sieht es Mau aus, da habe ich nur das was du ueber das Baumenu aufrufen kannst, da konnte ich zumindest die UUID vom Farn eintragen und das sieht ja fuer Simintern nicht schlecht aus. Hast du irgendwo auch eine Region laufen, das man sich das normalerweise funktionierende Ergebnis mal ansehen kann?
lg
Ezry
RE: Auto Plant Skript - Manfred Aabye - 22.07.2026
Ich habe das Komplettpaket in OSGrid in der Wright Plaza Mall auf Wright Plaza (158, 33, 21) in meinen Shop gestellt.
RE: Auto Plant Skript - Mareta Dagostino - 22.07.2026
Danke Manfred, ich war dort. Die Box ist allerdings weder zu Kopieren noch zu "Kaufen". Nur den Content könnte ich einzeln rauspflücken. Ist das so gedacht?
Und möglicherweise eine Frage, deren Antwort für dich selbstverständlich ist, und ich oute mich jetzt als total unwissend: Wie verhält es sich mit den Pflanzen, Felsen, Texturen, wenn ich das in einem anderen Grid rezzen will, und das Script nur auf GUIDs verweist, ohne die Objekte im Content dabei zu haben?
-----------
(EDIT: Ich hatte versehentlich URL statt GUID geschrieben.)
RE: Auto Plant Skript - Manfred Aabye - 23.07.2026
Es sind 2 Boxen in dieser Box, eine ist Auto-Plant und die andere Texturen.
Stelle die Texturen in dein Grid und kopiere diese Box. (Jetzt sind die Texturen in deinem Grid)
Arbeite mit deinen in deinem Grid kopierten Boxen nicht mit der Box, die du aus fremden Grids kopiert hast.
Die Materialien kopierst du in dein Inventar unter Materialien, die Texturen unter Texturen so hast du kompletten zugriff darauf.
Die Objekte sind im Würfel "Auto Plant 2.27", die Texturen im anderen Würfel.
Kopierproblem behoben.
RE: Auto Plant Skript - Mareta Dagostino - 23.07.2026
Vielen Dank Manfred, es hat jetzt funktioniert!
Grüße, Mareta
|