16.07.2026, 20:41
(Dieser Beitrag wurde zuletzt bearbeitet: 16.07.2026, 20:51 von Manfred Aabye.)
Auto Plant 1.14
Neues Inworld Skript in gepanschtem OSSL LSL.
Automatische Größenerkennung.
Es setzt PBR Material.
Raut die Region leicht auf.
Setzt Bäume (Jeder Baum wird dabei um 15 Grad gedreht).
Es fehlt noch: Todholz, Büsche, Steine, Gräser, Farne.
Es sind 3 unterschiedliche Bäume enthalten und es gibt eine Kiste mit Material bei mir.
Fazit: Es ist noch nicht ganz fertig zur Demo ist das aber schon gut genug.
Neues Inworld Skript in gepanschtem OSSL LSL.
Automatische Größenerkennung.
Es setzt PBR Material.
Raut die Region leicht auf.
Setzt Bäume (Jeder Baum wird dabei um 15 Grad gedreht).
Es fehlt noch: Todholz, Büsche, Steine, Gräser, Farne.
Es sind 3 unterschiedliche Bäume enthalten und es gibt eine Kiste mit Material bei mir.
Fazit: Es ist noch nicht ganz fertig zur Demo ist das aber schon gut genug.
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;
float ROTATION_SCHRITT = 15.0;
float AKTUELLE_ROTATION = 0.0;
// ===== BAUM-KONFIGURATIONEN =====
list BAUM_HOEHEN = [
"European-Beech-tree-A", 10.0,
"European-Beech-tree-B", 10.0,
"European-Oak-tree", 12.0
];
// ===== TERRAIN-TEXTUREN =====
float TextureLow = 10.0;
float TextureHigh = 30.0;
key Terrain_Dirt = "9dc31f61-e30b-44bf-91dc-e4f6a8735407";
key Terrain_Grass = "20a4e1b3-be0f-45ae-9683-54809ac750f7";
key Terrain_Mountain = "ebf2583d-0d94-4066-a684-e39b37fe2f57";
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 getTreeHeight(string treeName)
{
integer index = llListFindList(BAUM_HOEHEN, [treeName]);
if (index != -1)
return llList2Float(BAUM_HOEHEN, index + 1);
return 10.0;
}
rotation getRotation(float grad)
{
return llEuler2Rot(<0.0, 0.0, grad * DEG_TO_RAD>);
}
// ===== TERRAIN-FUNKTIONEN MIT AUFRAUUNG =====
setTerrain()
{
// 1. Texturen setzen (wie gehabt)
list textures = [Terrain_Dirt, Terrain_Grass, Terrain_Mountain, Terrain_Rock];
integer types = 2; // Legacy + PBR
osSetTerrainTextures(textures, types);
// Fallback für ältere Systeme
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);
// 2. Terrain aufrauen für besseren PBR-Effekt
// ACHTUNG: llModifyLand benötigt Estate-Manager-Rechte!
llModifyLand(LAND_NOISE, 0); // 0, 1, 2 ,3, 4
// 3. Terrain aktualisieren
osTerrainFlush();
llOwnerSay("✅ Terrain-Texturen wurden gesetzt und leicht 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 + " Rot: " + (string)((integer)AKTUELLE_ROTATION) + "°", <1,1,1>, 1.0);
integer gIntTreePick = (integer) llFrand(gFltRandMax + 1);
float fltDoIRez = llFrand(1.0);
if (fltDoIRez < gFltPlantProbability)
{
string gStrTreeName = llGetInventoryName(INVENTORY_OBJECT, gIntTreePick);
if (gStrTreeName != "")
{
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);
float treeHeight = getTreeHeight(gStrTreeName);
rotation treeRotation = getRotation(AKTUELLE_ROTATION);
llRezObject(gStrTreeName,
llGetPos() + <0.0, 0.0, treeHeight>,
<0.0, 0.0, 0.0>,
treeRotation,
0);
AKTUELLE_ROTATION += ROTATION_SCHRITT;
if (AKTUELLE_ROTATION >= 360.0)
AKTUELLE_ROTATION -= 360.0;
llSleep(0.1);
}
}
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 = .5;
integer count = llGetInventoryNumber(INVENTORY_OBJECT);
gFltRandMax = (float)count;
gIntZ = 0;
gIntRunning = TRUE;
gIntCurrentX = gIntStartX + (PFLANZABSTAND / 2);
gIntCurrentY = gIntStartY + (PFLANZABSTAND / 2);
AKTUELLE_ROTATION = 0.0;
llOwnerSay("? Starte Pflanzvorgang... Klicke erneut zum Stoppen.");
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)
{
// Wenn gerade gepflanzt wird, soll ein Klick den Vorgang stoppen
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;
}
// Ansonsten: Dialog-Menü anzeigen
key toucher = llDetectedKey(0);
llListenRemove(listenHandle);
listenHandle = llListen(MENU_CHANNEL, "", toucher, "");
llDialog(toucher, MENU_TEXT, MENU_BUTTONS, MENU_CHANNEL);
llSetTimerEvent(60.0); // Timeout nach 60 Sekunden
}
listen(integer channel, string name, key id, string message)
{
// Timeout zurücksetzen, da eine Auswahl getroffen wurde
llSetTimerEvent(0.0);
llListenRemove(listenHandle);
if (message == "? Pflanzen")
{
llOwnerSay("? Starte Pflanzvorgang...");
startPlanting();
}
else if (message == "? Terrain")
{
setTerrain();
// Optional: Kurze Bestätigung im Dialog
llDialog(id, "✅ Terrain-Texturen wurden aktualisiert.", ["OK"], MENU_CHANNEL);
}
else if (message == "❌ Schließen")
{
llOwnerSay("Menü geschlossen.");
}
else if (message == "OK")
{
// Nur für die Bestätigung nach Terrain-Update
llOwnerSay("✅ OK.");
}
}
timer()
{
// Timeout: Menü und Listener schließen
llSetTimerEvent(0.0);
llListenRemove(listenHandle);
llOwnerSay("⏳ Menü abgelaufen. Klicke erneut für Optionen.");
llSetText("Bereit - Klicke für Menü", <0,1,0>, 1.0);
}
}
Ein Metaversum sind viele kleine Räume, die nahtlos aneinander passen,
sowie direkt sichtbar und begehbar sind, als wäre es aus einem Guss.
sowie direkt sichtbar und begehbar sind, als wäre es aus einem Guss.

