// Version history (newest first): // 1.0.0 2026-07-14 initial: one-command fleet setup for every owned object // // ===================================================================== // SimWind - SETUP HUD (OpenSim / Second Life) // // Entwickler: [AJTech] Adrian Jenkins @ Misfitz Grid // Mail: AdrianJenkins3497@gmx.net // --------------------------------------------------------------------- // Wear this, type your fleet id once, and every SimWind object you own // in the region picks it up - boats, wind masts, receivers, bridges. // No notecards, nothing to name exactly right, nothing to paste. // // USE // Touch it and pick "Set fleet", or just type on channel 9: // /9 simwind my-club // Objects save the id in their own description, so it sticks through // a reset or a take-and-rez - and a boat you COPY is already set up // for whoever you hand it to. // // RANGE: the whole region, but only objects you own. Someone else's // boat on the same water is unaffected, and cannot be affected. // // This HUD does not need your fleet's API key and must never be given // one: it only names the fleet, which is public anyway. Steering the // wind is the instructor HUD's job (simwind_hud.lsl), and that one // keeps its key in a notecard where chat cannot reach it. // ===================================================================== // Must match SETUP_CHAN in the SimWind objects. integer SETUP_CHAN = 9; integer gMenuChan; integer gMenuListen = 0; integer gTextChan; integer gTextListen = 0; string gLast = ""; // last id sent, for the menu's display // A fleet id is 3-32 chars of a-z, 0-9 and '-'. Caught here so a typo gets an // answer straight away; the server is the real authority. integer valid_fleet_id(string s) { integer n = llStringLength(s); if (n < 3 || n > 32) return FALSE; integer i; for (i = 0; i < n; i++) { string c = llGetSubString(s, i, i); if (llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789-", c) == -1) return FALSE; } return TRUE; } // Tell every SimWind object in the region. They accept it because we are owned // by the same avatar they are - see setup_cmd() in those scripts. push(string id) { llRegionSay(SETUP_CHAN, "simwind " + id); gLast = id; llOwnerSay("[SimWind setup] sent fleet '" + id + "' to your SimWind objects in this region."); llOwnerSay("Each one that heard it will say so. Objects in other regions need it sent there too."); llSetText("SimWind\n" + id, <0.6, 0.9, 1.0>, 1.0); } menu(key av) { llListenRemove(gMenuListen); gMenuListen = llListen(gMenuChan, "", av, ""); string cur = gLast; if (cur == "") cur = "(none sent yet)"; llDialog(av, "\nSimWind setup\n\nLast fleet sent: " + cur + "\n\n" + "\"Set fleet\" asks for the id and sends it to every SimWind object you\n" + "own in this region. You can also type it directly: /9 simwind my-club", ["Set fleet", "Re-send", "Close"], gMenuChan); } ask(key av) { llListenRemove(gTextListen); gTextListen = llListen(gTextChan, "", av, ""); llTextBox(av, "\nType your fleet id (from your dashboard at simwind.net).\n\n" + "Lower-case letters, digits and hyphens.", gTextChan); } default { state_entry() { gMenuChan = -2100000 - (integer)llFrand(100000.0); gTextChan = -2200000 - (integer)llFrand(100000.0); // Owner-typed setup works from this HUD too, so you can skip the menu. llListen(SETUP_CHAN, "", llGetOwner(), ""); llSetText("SimWind\nsetup", <0.6, 0.9, 1.0>, 1.0); } touch_start(integer n) { if (llDetectedKey(0) != llGetOwner()) return; menu(llDetectedKey(0)); } listen(integer chan, string name, key id, string msg) { if (chan == SETUP_CHAN) { // The owner typed "/9 simwind ". The objects hear that for // themselves, so there is nothing to forward - just track it for // the menu display. (Re-saying it here would loop.) list w = llParseString2List(llToLower(llStringTrim(msg, STRING_TRIM)), [" "], []); if (llList2String(w, 0) == "simwind" && valid_fleet_id(llList2String(w, 1))) { gLast = llList2String(w, 1); llSetText("SimWind\n" + gLast, <0.6, 0.9, 1.0>, 1.0); } return; } if (chan == gMenuChan) { llListenRemove(gMenuListen); gMenuListen = 0; if (msg == "Set fleet") ask(id); else if (msg == "Re-send" && gLast != "") push(gLast); else if (msg == "Re-send") llOwnerSay("[SimWind setup] nothing to re-send yet."); return; } if (chan == gTextChan) { llListenRemove(gTextListen); gTextListen = 0; string want = llToLower(llStringTrim(msg, STRING_TRIM)); if (want == "") return; if (!valid_fleet_id(want)) { llOwnerSay("[SimWind setup] '" + want + "' is not a fleet id " + "(3-32 chars: a-z, 0-9, '-')."); return; } push(want); } } }