1 November 2014
This is a simple town crier, probably best suited for role-play SIMs however it could be used for any location where updates and news have to be broadcasted on the SIM. The script uses a configuration file such that different parameters can be configured.
To set it up, you will need to create a notecard called configuration
and drop it along with the script inside the same primitive. An example documented configuration
notecard is the following:
########################### START CONFIGURATION ############################## # the amount of time in seconds between the shout-outs interval = 60 # whether to randomize the interval so that a speak can occur between [0.045, interval] seconds. randomize = true # list of avatars that are able to toggle the town crier on and off access = Morgan LeFay, Frank Black # sound level can be region, shout, say or whisper level = say # channel to say the message on (0 is local chat) # note that if you set level to region, then the channel cannot be 0 channel = 0 ########################### END CONFIGURATION ###############################
After that, you can create any number of notecards named sequentially, something like:
crier_1 crier_2
and inside those notecards you can add lines that the town crier will speak.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// // for notecard reading integer line = 0; key request = NULL_KEY; // key-value data will be read into this list list tuples = []; // town cries list cards = []; integer size = 0; string card = ""; default { state_entry() { if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { llSay(DEBUG_CHANNEL, "Sorry, could not find a configuration notecard in the inventory."); return; } request = llGetNotecardLine("configuration", line); } dataserver(key id, string data) { if(id != request) return; if(data == EOF) state read; // invariant, length(tuples) % 2 == 0 if(data == "") jump continue; integer i = llSubStringIndex(data, "#"); if(i != -1) data = llDeleteSubString(data, i, -1); list o = llParseString2List(data, ["="], []); string k = llStringTrim(llList2String(o, 0), STRING_TRIM); string v = llStringTrim(llList2String(o, 1), STRING_TRIM); if(k == "" || v == "") jump continue; tuples += k; tuples += v; @continue; request = llGetNotecardLine("configuration", ++line); } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state read { state_entry() { integer i = llGetInventoryNumber(INVENTORY_NOTECARD)-1; do { string name = llGetInventoryName(INVENTORY_NOTECARD, i); if(llList2String(llParseString2List(name, ["_"], []), 0) != "cries") jump continue; cards += name; @continue; } while(--i>-1); if(llGetListLength(cards) == 0) { llSay(DEBUG_CHANNEL, "No cries notecards in the inventory."); return; } state sleep; } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state sleep { state_entry() { integer time = llList2Integer( tuples, llListFindList( tuples, (list)"interval" ) + 1 ); if( llToLower( llList2String( tuples, llListFindList( tuples, (list)"randomize" ) + 1 ) ) == "true") { llSetTimerEvent(0.045 + llFrand(time)); return; } llSetTimerEvent(time); } timer() { llSetTimerEvent(0); state select; } touch_start(integer num) { string name = llToLower(llDetectedName(0)); list access = llParseString2List( llList2String( tuples, llListFindList( tuples, (list)"access" )+1 ), [","], [] ); do { if(llToLower(llStringTrim(llList2String(access, 0), STRING_TRIM)) == name) { // authorized jump menu; } access = llDeleteSubList(access, 0, 0); } while(llGetListLength(access) != 0); return; @menu; key id = llDetectedKey(0); integer channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6)); llListen(channel, "", id, ""); llDialog(id, "\n Town Crier.\n\nCreated in 2014 by Wizardry and Steamworks\n 1 November 2014: Version: 1.1", [ "◉ ON" ], channel); } listen(integer channel, string name, key id, string message) { if(message == "◉ ON") { llSay(0, "The Town Crier is now switched OFF."); state pause; } } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state select { state_entry() { card = llList2String( cards, (integer)llFrand( llGetListLength( cards ) ) ); request = llGetNumberOfNotecardLines(card); } dataserver(key id, string data) { if(id != request) return; if(data == "") state sleep; size = (integer)data; state cry; } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state cry { state_entry() { request = llGetNotecardLine(card, (integer)llFrand(size)); } dataserver(key id, string data) { if(id != request) return; if(data == "") state sleep; string level = llToLower( llList2String( tuples, llListFindList( tuples, (list)"level" )+1 ) ); integer channel = llList2Integer( tuples, llListFindList( tuples, (list)"channel" )+1 ); if(level == "region") { if(channel != 0) { llRegionSay(channel, data); jump done; } llSay(DEBUG_CHANNEL, "Channel cannot be zero for region say."); jump done; } if(level == "shout") { llShout(0, data); jump done; } if(level == "say") { llSay(0, data); jump done; } if(level == "whisper") { llWhisper(0, data); jump done; } @done; state sleep; } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state pause { touch_start(integer num) { string name = llToLower(llDetectedName(0)); list access = llParseString2List( llList2String( tuples, llListFindList( tuples, (list)"access" )+1 ), [","], [] ); do { if(llToLower(llStringTrim(llList2String(access, 0), STRING_TRIM)) == name) { // authorized jump menu; } access = llDeleteSubList(access, 0, 0); } while(llGetListLength(access) != 0); return; @menu; key id = llDetectedKey(0); integer channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6)); llListen(channel, "", id, ""); llDialog(id, "\n Town Crier.\n\nCreated in 2014 by Wizardry and Steamworks\n 1 November 2014: Version: 1.1", [ "◯ OFF" ], channel); } listen(integer channel, string name, key id, string message) { if(message == "◯ OFF") { llSay(0, "The Town Crier is now switched ON."); state pause; } } on_rez(integer num) { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } }