// Wolf weather - ask it in local chat. Say "what is the weather now", "what's the weather", "will it rain later" or // "weather forecast" near it and it answers you. Touch it (owner only) to switch it on or off. // Works on any Wolf Territories region. (wolf-commands 1.2.0: wolfCall weather.text) // // It answers only the person who asked (llRegionSayTo), at most once every 20 seconds each and once every 5 seconds in // all, so it cannot be used to flood the chat. integer PERSON_WAIT = 20; // seconds before the same person gets another answer integer ALL_WAIT = 5; // seconds between any two answers integer MAX_REMEMBERED = 40; // people remembered for PERSON_WAIT (oldest forgotten first) integer gOn = TRUE; integer gListen; integer gLastAnswer; list gAsked; // [avatar, unix time, ...] list gWaiting; // [query key, avatar, ...] questions waiting for their answer // What they asked for: "now", "later", "stats" - or "" when it is not a weather question. string kindOf(string msg) { string m = llToLower(msg); if (llSubStringIndex(m, "weather") == -1 && llSubStringIndex(m, "rain") == -1 && llSubStringIndex(m, "snow") == -1 && llSubStringIndex(m, "forecast") == -1 && llSubStringIndex(m, "temperature") == -1) return ""; // a question or a request, not every sentence that mentions rain if (llSubStringIndex(m, "?") == -1 && llSubStringIndex(m, "what") == -1 && llSubStringIndex(m, "will it") == -1 && llSubStringIndex(m, "forecast") == -1 && llSubStringIndex(m, "how") == -1 && llSubStringIndex(m, "is it") == -1) return ""; if (llSubStringIndex(m, "stats") != -1 || llSubStringIndex(m, "detail") != -1 || llSubStringIndex(m, "report") != -1) return "stats"; if (llSubStringIndex(m, "later") != -1 || llSubStringIndex(m, "forecast") != -1 || llSubStringIndex(m, "tonight") != -1 || llSubStringIndex(m, "tomorrow") != -1 || llSubStringIndex(m, "will it") != -1) return "later"; return "now"; } integer mayAnswer(key who) { integer now = llGetUnixTime(); if (now - gLastAnswer < ALL_WAIT) return FALSE; integer i = llListFindList(gAsked, [who]); if (i != -1) { if (now - llList2Integer(gAsked, i + 1) < PERSON_WAIT) return FALSE; gAsked = llDeleteSubList(gAsked, i, i + 1); } gAsked += [who, now]; if (llGetListLength(gAsked) > MAX_REMEMBERED * 2) gAsked = llDeleteSubList(gAsked, 0, 1); gLastAnswer = now; return TRUE; } show() { if (gOn) llSetText("Ask me about the weather", <0.7, 0.9, 1.0>, 1.0); else llSetText("Weather (off)", <0.6, 0.6, 0.6>, 1.0); } default { state_entry() { gListen = llListen(0, "", NULL_KEY, ""); show(); } on_rez(integer p) { llResetScript(); } touch_start(integer n) { if (llDetectedKey(0) != llGetOwner()) return; gOn = !gOn; llListenControl(gListen, gOn); show(); llOwnerSay("Weather answers " + llList2String(["off", "on"], gOn) + "."); } listen(integer ch, string name, key id, string msg) { if (!gOn || llGetAgentSize(id) == ZERO_VECTOR) return; // people only, not objects string kind = kindOf(msg); if (kind == "" || !mayAnswer(id)) return; // "later" is about six hours ahead; weather.text also takes a number of hours (1-48). key q = wolfCallAsync("weather.text", [kind]); if (q == NULL_KEY) { llRegionSayTo(id, 0, wolfGetLastError()); return; } gWaiting += [q, id]; if (llGetListLength(gWaiting) > 20) gWaiting = llDeleteSubList(gWaiting, 0, 1); } dataserver(key q, string data) { integer i = llListFindList(gWaiting, [q]); if (i == -1) return; key who = llList2Key(gWaiting, i + 1); gWaiting = llDeleteSubList(gWaiting, i, i + 1); if (llGetSubString(data, 0, 5) == "error:") data = "Sorry, I can't tell just now: " + llGetSubString(data, 7, -1); llRegionSayTo(who, 0, data); } }