// Wolf weather board - shows this region's weather as floating text and makes it rain or snow on the board when it // does here. Put it in a prim; it works on any Wolf Territories region. (wolf-commands 1.2.0: wolfCall weather.*) // // It asks every 5 minutes: the region keeps the weather for 5 minutes anyway, so asking more often only gives the // same answer. Touch it to see the full stats in local chat. float REFRESH = 300.0; // seconds between looks key gAsk; // the weather.now question waiting for its answer key gStats; // the weather.text "stats" question string num(string json, list path, integer places) { string v = llJsonGetValue(json, path); if (v == JSON_INVALID || v == JSON_NULL) return "?"; float f = (float)v; if (places == 0) return (string)llRound(f); // one decimal place integer tenths = llRound(f * 10.0); string s = (string)(tenths / 10) + "." + (string)llAbs(tenths % 10); if (tenths < 0 && tenths > -10) s = "-" + s; return s; } falling(string kind) { if (kind == "rain" || kind == "sleet") { llParticleSystem([ PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE, PSYS_SRC_ANGLE_BEGIN, 0.0, PSYS_SRC_ANGLE_END, PI, PSYS_PART_START_COLOR, <0.7, 0.8, 1.0>, PSYS_PART_START_ALPHA, 0.6, PSYS_PART_START_SCALE, <0.03, 0.25, 0.0>, PSYS_SRC_ACCEL, <0.0, 0.0, -9.0>, PSYS_SRC_BURST_RATE, 0.05, PSYS_SRC_BURST_PART_COUNT, 6, PSYS_SRC_BURST_RADIUS, 1.5, PSYS_PART_MAX_AGE, 1.2, PSYS_SRC_BURST_SPEED_MIN, 0.1, PSYS_SRC_BURST_SPEED_MAX, 0.3]); } else if (kind == "snow") { llParticleSystem([ PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_WIND_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE, PSYS_SRC_ANGLE_BEGIN, 0.0, PSYS_SRC_ANGLE_END, PI, PSYS_PART_START_COLOR, <1.0, 1.0, 1.0>, PSYS_PART_START_ALPHA, 0.9, PSYS_PART_START_SCALE, <0.08, 0.08, 0.0>, PSYS_SRC_ACCEL, <0.0, 0.0, -0.6>, PSYS_SRC_BURST_RATE, 0.1, PSYS_SRC_BURST_PART_COUNT, 3, PSYS_SRC_BURST_RADIUS, 1.5, PSYS_PART_MAX_AGE, 5.0, PSYS_SRC_BURST_SPEED_MIN, 0.05, PSYS_SRC_BURST_SPEED_MAX, 0.2]); } else llParticleSystem([]); } ask() { // wolfCallAsync answers in dataserver when the weather is ready (the very first look on a region can take a second). gAsk = wolfCallAsync("weather.now", ["json"]); if (gAsk == NULL_KEY) llSetText("Weather: " + wolfGetLastError(), <1.0, 0.6, 0.6>, 1.0); } default { state_entry() { llSetText("Reading the weather...", <1.0, 1.0, 1.0>, 1.0); ask(); llSetTimerEvent(REFRESH); } on_rez(integer p) { llResetScript(); } timer() { ask(); } touch_start(integer n) { gStats = wolfCallAsync("weather.text", ["stats"]); if (gStats == NULL_KEY) llRegionSayTo(llDetectedKey(0), 0, wolfGetLastError()); } dataserver(key q, string data) { if (llGetSubString(data, 0, 5) == "error:") { if (q == gAsk) llSetText("Weather: " + llGetSubString(data, 7, -1), <1.0, 0.6, 0.6>, 1.0); else if (q == gStats) llSay(0, llGetSubString(data, 7, -1)); return; } if (q == gStats) { llSay(0, data); return; } if (q != gAsk) return; if (llJsonGetValue(data, ["available"]) != JSON_TRUE) { llSetText("No weather here\n" + llJsonGetValue(data, ["reason"]), <0.8, 0.8, 0.8>, 1.0); falling("none"); return; } string place = llJsonGetValue(data, ["place", "short"]); string text = llJsonGetValue(data, ["now", "condition"]) + "\n"; if (llJsonGetValue(data, ["now", "temperature_c"]) != JSON_NULL) text += num(data, ["now", "temperature_c"], 1) + " °C (feels like " + num(data, ["now", "feels_like_c"], 0) + " °C)\n"; if (llJsonGetValue(data, ["now", "humidity"]) != JSON_NULL) text += "Humidity " + num(data, ["now", "humidity"], 0) + "%\n"; text += "Wind " + num(data, ["now", "wind_ms"], 1) + " m/s from the " + llJsonGetValue(data, ["now", "wind_compass"]) + "\n"; if (llJsonGetValue(data, ["place", "local_time24"]) != JSON_INVALID) text += place + " time " + llJsonGetValue(data, ["place", "local_time24"]) + "\n"; text += llJsonGetValue(data, ["attribution", "text"]); llSetText(text, <1.0, 1.0, 1.0>, 1.0); // Rain, sleet or snow on the board while it falls here. string kind = llJsonGetValue(data, ["now", "precip_type"]); if (llJsonGetValue(data, ["now", "kind"]) == "clear") kind = "none"; falling(kind); } }