Difference between revisions of "Random AV Particle Name Generator"
(New page: PAGE IN PROGRESS. RETURN SOON) |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{LSL Header}} | |||
'''~ PARTICLE TEXT GENERATOR AV SE v1.0 by Debbie Trilling ~''' | |||
'''Set-up, configuration and operation Help:''' http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator | |||
'''Profile:''' http://wiki.secondlife.com/wiki/User:Debbie_Trilling | |||
<lsl> | |||
// ~ PARTICLE TEXT GENERATOR AV SE v1.0 by Debbie Trilling ~ | |||
// This script performs two functions: | |||
// 1) scans a crowd, randomly picks an AV and the displays their first name in an attractive particle stream. EG: "Joe Smith" will be "HI JOE" in particles | |||
// 2) creates an attractive particle text banner from a selection of your choosing. EG: "HAPPY REZ DAY" "PARTICLE CRUCIBLE", "MY STORE NAME" | |||
// Based on the original XYText work of Xylor Baysklef and an in-world script attributed to Zara Vale. | |||
// All new functionality and code improvements by Debbie Trilling. | |||
// Script is free to use and modify as you wish but under the condition that the title and this introduction | |||
// remain in place, and that due credit continues to be given to Xylor Baysklef, Zara Vale & Debbie Trilling. | |||
// Fonts and their texture UUIDS may be used but only under recognision that they were created by | |||
// Debbie Trilling specifically for the 'Particle Crucible' brand and further, that no attempt is made to sell them or use them for any other branding purposes | |||
// BRIEF INSTRUCTIONS: | |||
// Full instructions at http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator | |||
// It is controlled from a dialog menu. Simply put the script in a prim and 'touch'. Make a selection from the buttons. | |||
// To change the default text to a selection of your own choice, change the text in 'DefaultTextPalette' a few lines below. | |||
// Rather than display the same AV name twice in a row, on the second time it will display a random selection from the default text | |||
// The bigger the prim that you put this script into, the further away you will be able to see the particle text | |||
// Rotate the prim to have the text travel horizontally rather than vertically | |||
// ** PARAMETERS THAT YOU CAN CHANGE ** | |||
// the default text palette, one of which that will be displayed when no agents have been detected | |||
list DefaultTextPalette = ["Particle Crucible", "Particle Garden", "SpoLand", "Cartoonimals"]; | |||
//************************ | |||
// ** DO NOT CHANGE BELOW THIS LINE ** | |||
//************************ | |||
// particle variables | |||
list WorkCharIndex = []; | |||
list WorkUUIDPalette = []; | |||
float Radius = 0.50; | |||
float FontSize = 1.40; | |||
// Control variables | |||
integer Power = FALSE; | |||
string PowerText = "On"; | |||
key ObjectOwner = ""; | |||
key LastTarget = ""; | |||
string WorkChar = ""; | |||
integer NoSensorCounter = 0; | |||
integer ListenChannel = 0; | |||
list MenuItems = []; | |||
string MenuText = ""; | |||
// this is the text that will be displayed this iteration | |||
string WorkDisplayText = ""; | |||
// controls gap between letters by time in seconds | |||
float LetterTimeGap = 2.7; | |||
// controls whether random AV names are displayed. | |||
integer FindRandomAV = TRUE; | |||
string FindRandomAVText = "Defaults"; | |||
// type of scan to be performedl | |||
float ScanArc = 3.141592653; | |||
string ScanArcText = "X-Axis"; | |||
// sensor range in meters. | |||
float Range = 25.00; | |||
// list of possible scan range options | |||
list ScannerItems = ["75m", "90m","40m", "50m", "60m", "25m", "30m", "35m", "10m", "15m", "20m" ]; | |||
// Characters in 'The Particle Crucible' branded font | |||
// Fonts remade in Photoshop CS3 by Debbie Trilling based on the 'Happy Days' font | |||
list MasterUUIDPalette = [ | |||
"342005c0-e916-015a-1d9f-f5a5282658d6", //A | |||
"3ceaeb61-7877-347f-200c-389b008dfba2", //B | |||
"a767bfba-3580-48e5-bf82-843c69996828", //C | |||
"3774a58b-b0a2-68d5-4a3a-ce1f85f719b7", //D | |||
"b214c1c0-774a-becf-8a6f-4a771b3a16fb", //E | |||
"ae3792c0-33e7-0de5-4c98-6e1cfa7a4c4c", //F | |||
"694b92e3-bdec-534a-52c4-b955685ab109", //G | |||
"dfd35eec-7232-26f8-bdd0-ce9a7c142451", //H | |||
"18a70d23-254a-0a3c-4d4b-c6692f5941b3", //I | |||
"b05d6f5f-2b1b-ff7c-2951-ec1f68238c90", //J | |||
"4df1867f-bf31-17d5-3b88-d5703a782c46", //K | |||
"1812a48f-0ee8-de20-b7d8-a33cff922303", //L | |||
"d2bb1c89-5e3c-b084-33f1-a723e5ceb005", //M | |||
"74a39f5d-0aa8-f7c1-e5b2-7ca6470b1877", //N | |||
"340a9361-8f00-5e8c-ef41-89fb25fc26b9", //O | |||
"d8b0f853-ee63-6248-ea70-bd0806fe5259", //P | |||
"6dc7465d-bb3d-c664-98a1-15293d1c1973", //Q | |||
"a45ee3fa-102a-32ce-140a-73c11fd3e873", //R | |||
"378bf10c-86f7-69e5-d6cb-3a27bfa9ed0a", //S | |||
"e8170991-11bd-e2e4-3662-d4b265d785ae", //T | |||
"0541fb80-0055-3815-04d1-fbb2c10e9a59", //U | |||
"45d0a340-32c1-f95a-0a76-7f96c1675d55", //V | |||
"7c8f2c6e-1e44-1af7-4c2b-15c40fa1273d", //W | |||
"0694bea0-21c0-67ec-f420-05e1a5e76e69", //X | |||
"2de3d529-95e8-64a7-45d0-f7e497bf7480", //Y | |||
"558a2f3a-5e76-f0c6-32ad-2db1258250f8", //Z | |||
"75ef778c-cbb2-9a59-8044-49e37753dcfe", //1 | |||
"2ed7ef82-2770-b316-b796-84fec6273270", //2 | |||
"50fe9926-264a-2017-c7c4-f1ff8a0677eb", //3 | |||
"bccfb0e1-1ace-a919-1ca5-ee2387011129", //4 | |||
"c38898d2-8b84-eb09-6f63-f88fe8ce62ec", //5 | |||
"829e0036-75b0-54a0-2515-6ba1c01b5272", //6 | |||
"e84d0ad8-ff28-ba59-4d8e-698f5fc96311", //7 | |||
"c8a80085-079e-a00a-6ec4-7c0a82782043", //8 | |||
"57df7103-c08f-58b7-5f78-a22d5c200d58", //9 | |||
"c259edf8-9875-da57-34a2-d2428e39afb9", //ZERO | |||
"701917a8-d614-471f-13dd-5f4644e36e3c" // Space | |||
]; | |||
list MasterCharIndex = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0"," "]; | |||
// product variables | |||
string Author = "Debbie Trilling"; | |||
string Supplier = "The Particle Crucible"; | |||
string ObjectName = "Particle Text Generator AV SE"; | |||
string Version = " v1.0"; | |||
// sets the number of consecutive times that the scanner is allowed to operate without having located an AV within range | |||
// eg: if RepeatTime = 60.0 seconds and TotalNoScansAllowed = 30, then the toy will operate for 1800 seconds (60x30, or 30 minutes) without locating | |||
// anyone before it automatically powers down. Set to '0' to disable the auto-off function | |||
integer TotalNoScansAllowed = 0; | |||
InitialiseObject() | |||
{ | |||
Power = FALSE; | |||
PowerText = "On"; | |||
ObjectOwner = llGetOwner(); | |||
llSetObjectName(ObjectName + Version); | |||
llSetObjectDesc("supplied courtesy of " + Author + "'s " + Supplier); | |||
// set the particle radius to be 0.50m above the prim | |||
vector PrimSize = llGetScale(); | |||
Radius = ((PrimSize.z / 2) + (FontSize/2)) + 0.50; | |||
AnnounceWelcome(); | |||
StopOperation(); | |||
} | |||
AnnounceWelcome() | |||
{ | |||
llOwnerSay( | |||
"Thank you for your interest in this " + ObjectName + " " | |||
+ Version + " created by " + Author + " at " + Supplier + ". \nTouch to operate."); | |||
} | |||
MakeMenu() | |||
{ | |||
integer CommChannel = (-200000 - ((integer)llFrand(12345) * -1)); | |||
ListenChannel = llListen(CommChannel, "", ObjectOwner, ""); | |||
llDialog(ObjectOwner, MenuText, MenuItems, CommChannel); | |||
} | |||
StartOperation() | |||
{ | |||
WorkChar = ""; | |||
NoSensorCounter = 0; | |||
StartSensorCheck(); | |||
llOwnerSay( ObjectName + " has been turned ON"); | |||
} | |||
StartSensorCheck() | |||
{ | |||
// we dont want to use llSensorRepeat, cos it might kick-off a new scan before the previous name has been fully displayed | |||
// llSensor lets us control when we want a scan performing, which is not until after the previous text string has finished | |||
if (FindRandomAV) | |||
{ | |||
llSensor("",NULL_KEY, AGENT, Range, ScanArc); | |||
} | |||
else | |||
{ | |||
ApplyDefaultText(); | |||
} | |||
} | |||
StartParticle(string ParticleChar) | |||
{ | |||
llParticleSystem([ | |||
PSYS_PART_FLAGS, 0x100, | |||
PSYS_SRC_PATTERN, 0x04, | |||
PSYS_SRC_TEXTURE, llList2Key(WorkUUIDPalette, llListFindList(WorkCharIndex, (list)ParticleChar)), | |||
PSYS_PART_START_SCALE,<FontSize, FontSize, 0.0>, | |||
PSYS_PART_END_SCALE,<FontSize, FontSize, 0.0>, | |||
PSYS_PART_START_ALPHA,1.0, | |||
PSYS_PART_END_ALPHA,1.0, | |||
PSYS_PART_MAX_AGE, 30.0, | |||
PSYS_SRC_BURST_PART_COUNT, 1, | |||
PSYS_SRC_BURST_RADIUS, Radius, | |||
PSYS_SRC_BURST_RATE, LetterTimeGap, | |||
PSYS_SRC_MAX_AGE, LetterTimeGap, | |||
PSYS_SRC_BURST_SPEED_MIN,0.45, | |||
PSYS_SRC_BURST_SPEED_MAX,0.45 | |||
]); | |||
} | |||
PrepareData() | |||
{ | |||
// make a list index of unique characters | |||
MakeCharIndex(); | |||
// make a list containing only the UUID's of the characters we need for this name | |||
MakeTexturePalette(); | |||
// start processing the characters | |||
llSetTimerEvent(LetterTimeGap); | |||
} | |||
MakeCharIndex() | |||
{ | |||
// loop through WorkDisplayText letter-by-letter, add each unique character to list WorkCharIndex | |||
WorkCharIndex = []; | |||
integer x; | |||
integer y = llStringLength(WorkDisplayText); | |||
for (x = 0; x < y; x++) | |||
{ | |||
if (llListFindList(WorkCharIndex, (list)llGetSubString(WorkDisplayText, x, x)) == -1) | |||
{ | |||
WorkCharIndex = WorkCharIndex + (list)llGetSubString(WorkDisplayText, x, x); | |||
} | |||
} | |||
} | |||
MakeTexturePalette() | |||
{ | |||
// locate the required texture UUID's in MasterUUIDPalette and extract them out into list WorkUUIDPalette | |||
WorkUUIDPalette = []; | |||
integer x; | |||
integer y = llGetListLength(WorkCharIndex); | |||
for (x = 0; x < y; x++) | |||
{ | |||
WorkUUIDPalette = WorkUUIDPalette + (list)llList2Key(MasterUUIDPalette, llListFindList(MasterCharIndex, (list)llList2String(WorkCharIndex,x))); | |||
} | |||
} | |||
ApplyDefaultText() | |||
{ | |||
// select & assign a default text string for display, and add a space at the end, turn to upper case | |||
WorkDisplayText = llToUpper(llList2String(DefaultTextPalette, (integer)llFrand((float)llGetListLength(DefaultTextPalette)))) + " "; | |||
// put it all together | |||
PrepareData(); | |||
} | |||
SayScanSettings() | |||
{ | |||
string MessageLine = "Scans will be performed "; | |||
if (ScanArc == PI) | |||
{ | |||
MessageLine = MessageLine + "360 degrees around the prim"; | |||
} | |||
else | |||
{ | |||
MessageLine = MessageLine + "forward of the prim's local X-Axis"; | |||
} | |||
llOwnerSay(MessageLine + " with a range of " + (string)llFloor(Range) + "m."); | |||
} | |||
StopOperation() | |||
{ | |||
llSetTimerEvent(0.0); | |||
llSensorRemove(); | |||
llListenRemove(ListenChannel); | |||
llParticleSystem([]); | |||
} | |||
default | |||
{ | |||
on_rez(integer start_param) | |||
{ | |||
// reset on rez | |||
llResetScript(); | |||
} | |||
changed( integer change ) | |||
{ | |||
if(change & CHANGED_OWNER ) | |||
{ | |||
// reset script on change of Owner | |||
llResetScript(); | |||
} | |||
} | |||
state_entry() | |||
{ | |||
InitialiseObject(); | |||
} | |||
touch_start(integer num_detected) | |||
{ | |||
key DetectedUser = llDetectedKey(0); | |||
if (DetectedUser == ObjectOwner) | |||
{ | |||
// owner only operation | |||
if(Power) | |||
{ | |||
PowerText = "Off"; | |||
} | |||
else | |||
{ | |||
PowerText = "On"; | |||
} | |||
if (FindRandomAV) | |||
{ | |||
// Senor mode & 'SetRange' options are only avaliable if we scanning for random AV's | |||
MenuItems = [PowerText, FindRandomAVText, ScanArcText, "SetRange"]; | |||
} | |||
else | |||
{ | |||
MenuItems = [ PowerText, FindRandomAVText ]; | |||
} | |||
MenuItems = ["Close", "Help", "ResetScript"] + llListSort(MenuItems,1,TRUE); | |||
MenuText = "MAIN MENU: \n- On-Off: toggle power \n- Defaults-Names: toggle display mode \n- XAxis-360 degree: toggle if scan is forward of the prim, or all around it \n- SetRange: set scanner range \n- ResetScript: restore settings \n- Help: Link to product Help page"; | |||
MakeMenu(); | |||
} | |||
else | |||
{ | |||
llInstantMessage(DetectedUser, "Thank you for your interest in this " + ObjectName + " " | |||
+ Version + " created by " + Author + " at " + Supplier | |||
+ ". \nYou can get a free copy of this script at http://wiki.secondlife.com/wiki/User:Debbie_Trilling"); | |||
} | |||
} | |||
sensor(integer total_number) | |||
{ | |||
// locate a random AV target | |||
key IntendedTarget = llDetectedKey((integer)llFrand(total_number)); | |||
// did we use this AV last time? if so, display a default text string instead | |||
if (IntendedTarget == LastTarget) | |||
{ | |||
// we used this AV last time | |||
ApplyDefaultText(); | |||
LastTarget = ""; | |||
} | |||
else | |||
{ | |||
// this is a different AV so populate LastTarget for the check next time around | |||
LastTarget = IntendedTarget; | |||
// determine the first name of the random AV, turn to upper case, add a space to the end & assign to WorkDisplayText | |||
WorkDisplayText = "HI " + llToUpper(llGetSubString(llKey2Name(IntendedTarget), 0, (llSubStringIndex(llKey2Name(IntendedTarget), " ") -1))) + " "; | |||
// put it all together | |||
PrepareData(); | |||
} | |||
} | |||
no_sensor() | |||
{ | |||
// counts the number of times that the scanner doesn't find anyone in range. If TotalNoScansAllowed is set to greater than zero, automatically powers down the toy | |||
// when the number of no_sensors exceeds TotalNoScansAllowed. However, this functionality is disabled if TotalNoScansAllowed is set to zero. | |||
NoSensorCounter++; | |||
if ((NoSensorCounter > TotalNoScansAllowed) && (TotalNoScansAllowed > 0)) | |||
{ | |||
StopOperation(); | |||
llInstantMessage(ObjectOwner, "\nThe " + ObjectName + " has been automatically switched OFF as no Agents have been detected within the set timeframe."); | |||
} | |||
else | |||
{ | |||
ApplyDefaultText(); | |||
} | |||
} | |||
timer() | |||
{ | |||
// initialise WorkChar. This is the variable we will manipulate as we process the text string | |||
if(WorkChar == "") | |||
{ | |||
WorkChar = WorkDisplayText; | |||
} | |||
// fire the first character of the remaining string | |||
StartParticle(llGetSubString(WorkChar, 0, 0)); | |||
if(llStringLength(WorkChar) == 1) | |||
{ | |||
// this is the space character at the end, so prepare to re-initialise | |||
WorkChar = ""; | |||
StartSensorCheck(); | |||
} | |||
else | |||
{ | |||
// remove first character of remaining string, as we've now processed it | |||
WorkChar = llGetSubString(WorkChar, 1, -1); | |||
} | |||
} | |||
listen(integer channel, string name, key id, string message) | |||
{ | |||
// listen housekeeping | |||
llListenRemove(ListenChannel); | |||
message = llToLower(message); | |||
// process selection | |||
if ((message == "on") || (message == "off")) | |||
{ | |||
// toggle power | |||
if (message == "on") | |||
{ | |||
StartOperation(); | |||
} | |||
else | |||
{ | |||
StopOperation(); | |||
llOwnerSay( ObjectName + " has been turned OFF"); | |||
} | |||
Power = !Power; | |||
} | |||
else if ((message == "defaults") || (message == "names")) | |||
{ | |||
// toggle display mode | |||
if (message == "defaults") | |||
{ | |||
FindRandomAVText = "Names"; | |||
llOwnerSay("Particle stream will display default texts only"); | |||
} | |||
else | |||
{ | |||
FindRandomAVText = "Defaults"; | |||
llOwnerSay("Particle stream will display random names and default texts"); | |||
} | |||
FindRandomAV = !FindRandomAV; | |||
} | |||
else if ((message == "x-axis") || (message == "360degree")) | |||
{ | |||
// toggle sensor arc mode | |||
if (message == "x-axis") | |||
{ | |||
ScanArc = PI_BY_TWO; | |||
ScanArcText = "360degree"; | |||
} | |||
else | |||
{ | |||
ScanArc = PI; | |||
ScanArcText = "X-Axis"; | |||
} | |||
SayScanSettings(); | |||
} | |||
else if (message == "setrange") | |||
{ | |||
// send Scanner Range Menu | |||
MenuText = "SET SCANNER RANGE MENU: Please set the scanner range:"; | |||
MenuItems = (list)"Close" + ScannerItems; | |||
MakeMenu(); | |||
} | |||
else if (llListFindList(ScannerItems, (list)message) != -1) | |||
{ | |||
// derive the new range by removing the "m" from the end of 'message' | |||
Range = (float)llGetSubString(message, 0, 1); | |||
SayScanSettings(); | |||
} | |||
else if (message == "resetscript") | |||
{ | |||
llOwnerSay("Resetting script. Please wait..."); | |||
llResetScript(); | |||
} | |||
else if (message == "help") | |||
{ | |||
string URL_HELPPAGE = "http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator"; | |||
llLoadURL(ObjectOwner, "This link will take you to the " + ObjectName + "'s Help page.", URL_HELPPAGE); | |||
} | |||
else if (message == "close") | |||
{ | |||
// let fall thro' | |||
} | |||
else | |||
{ | |||
llOwnerSay("MAIN MENU: Unrecognised menu selection"); | |||
} | |||
} | |||
// default end | |||
} | |||
</lsl> |
Latest revision as of 15:53, 23 January 2008
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
~ PARTICLE TEXT GENERATOR AV SE v1.0 by Debbie Trilling ~
Set-up, configuration and operation Help: http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator
Profile: http://wiki.secondlife.com/wiki/User:Debbie_Trilling
<lsl>
// ~ PARTICLE TEXT GENERATOR AV SE v1.0 by Debbie Trilling ~
// This script performs two functions: // 1) scans a crowd, randomly picks an AV and the displays their first name in an attractive particle stream. EG: "Joe Smith" will be "HI JOE" in particles // 2) creates an attractive particle text banner from a selection of your choosing. EG: "HAPPY REZ DAY" "PARTICLE CRUCIBLE", "MY STORE NAME"
// Based on the original XYText work of Xylor Baysklef and an in-world script attributed to Zara Vale. // All new functionality and code improvements by Debbie Trilling.
// Script is free to use and modify as you wish but under the condition that the title and this introduction // remain in place, and that due credit continues to be given to Xylor Baysklef, Zara Vale & Debbie Trilling. // Fonts and their texture UUIDS may be used but only under recognision that they were created by // Debbie Trilling specifically for the 'Particle Crucible' brand and further, that no attempt is made to sell them or use them for any other branding purposes
// BRIEF INSTRUCTIONS:
// Full instructions at http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator
// It is controlled from a dialog menu. Simply put the script in a prim and 'touch'. Make a selection from the buttons.
// To change the default text to a selection of your own choice, change the text in 'DefaultTextPalette' a few lines below.
// Rather than display the same AV name twice in a row, on the second time it will display a random selection from the default text
// The bigger the prim that you put this script into, the further away you will be able to see the particle text
// Rotate the prim to have the text travel horizontally rather than vertically
// ** PARAMETERS THAT YOU CAN CHANGE **
// the default text palette, one of which that will be displayed when no agents have been detected
list DefaultTextPalette = ["Particle Crucible", "Particle Garden", "SpoLand", "Cartoonimals"];
//************************ // ** DO NOT CHANGE BELOW THIS LINE ** //************************
// particle variables list WorkCharIndex = []; list WorkUUIDPalette = []; float Radius = 0.50; float FontSize = 1.40;
// Control variables integer Power = FALSE; string PowerText = "On"; key ObjectOwner = ""; key LastTarget = ""; string WorkChar = ""; integer NoSensorCounter = 0; integer ListenChannel = 0; list MenuItems = []; string MenuText = ""; // this is the text that will be displayed this iteration string WorkDisplayText = ""; // controls gap between letters by time in seconds float LetterTimeGap = 2.7; // controls whether random AV names are displayed. integer FindRandomAV = TRUE; string FindRandomAVText = "Defaults"; // type of scan to be performedl float ScanArc = 3.141592653; string ScanArcText = "X-Axis"; // sensor range in meters. float Range = 25.00; // list of possible scan range options list ScannerItems = ["75m", "90m","40m", "50m", "60m", "25m", "30m", "35m", "10m", "15m", "20m" ];
// Characters in 'The Particle Crucible' branded font
// Fonts remade in Photoshop CS3 by Debbie Trilling based on the 'Happy Days' font
list MasterUUIDPalette = [
"342005c0-e916-015a-1d9f-f5a5282658d6", //A
"3ceaeb61-7877-347f-200c-389b008dfba2", //B
"a767bfba-3580-48e5-bf82-843c69996828", //C
"3774a58b-b0a2-68d5-4a3a-ce1f85f719b7", //D
"b214c1c0-774a-becf-8a6f-4a771b3a16fb", //E
"ae3792c0-33e7-0de5-4c98-6e1cfa7a4c4c", //F
"694b92e3-bdec-534a-52c4-b955685ab109", //G
"dfd35eec-7232-26f8-bdd0-ce9a7c142451", //H
"18a70d23-254a-0a3c-4d4b-c6692f5941b3", //I
"b05d6f5f-2b1b-ff7c-2951-ec1f68238c90", //J
"4df1867f-bf31-17d5-3b88-d5703a782c46", //K
"1812a48f-0ee8-de20-b7d8-a33cff922303", //L
"d2bb1c89-5e3c-b084-33f1-a723e5ceb005", //M
"74a39f5d-0aa8-f7c1-e5b2-7ca6470b1877", //N
"340a9361-8f00-5e8c-ef41-89fb25fc26b9", //O
"d8b0f853-ee63-6248-ea70-bd0806fe5259", //P
"6dc7465d-bb3d-c664-98a1-15293d1c1973", //Q
"a45ee3fa-102a-32ce-140a-73c11fd3e873", //R
"378bf10c-86f7-69e5-d6cb-3a27bfa9ed0a", //S
"e8170991-11bd-e2e4-3662-d4b265d785ae", //T
"0541fb80-0055-3815-04d1-fbb2c10e9a59", //U
"45d0a340-32c1-f95a-0a76-7f96c1675d55", //V
"7c8f2c6e-1e44-1af7-4c2b-15c40fa1273d", //W
"0694bea0-21c0-67ec-f420-05e1a5e76e69", //X
"2de3d529-95e8-64a7-45d0-f7e497bf7480", //Y
"558a2f3a-5e76-f0c6-32ad-2db1258250f8", //Z
"75ef778c-cbb2-9a59-8044-49e37753dcfe", //1
"2ed7ef82-2770-b316-b796-84fec6273270", //2
"50fe9926-264a-2017-c7c4-f1ff8a0677eb", //3
"bccfb0e1-1ace-a919-1ca5-ee2387011129", //4
"c38898d2-8b84-eb09-6f63-f88fe8ce62ec", //5
"829e0036-75b0-54a0-2515-6ba1c01b5272", //6
"e84d0ad8-ff28-ba59-4d8e-698f5fc96311", //7
"c8a80085-079e-a00a-6ec4-7c0a82782043", //8
"57df7103-c08f-58b7-5f78-a22d5c200d58", //9
"c259edf8-9875-da57-34a2-d2428e39afb9", //ZERO
"701917a8-d614-471f-13dd-5f4644e36e3c" // Space
];
list MasterCharIndex = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","1","2","3","4","5","6","7","8","9","0"," "];
// product variables
string Author = "Debbie Trilling";
string Supplier = "The Particle Crucible";
string ObjectName = "Particle Text Generator AV SE";
string Version = " v1.0";
// sets the number of consecutive times that the scanner is allowed to operate without having located an AV within range // eg: if RepeatTime = 60.0 seconds and TotalNoScansAllowed = 30, then the toy will operate for 1800 seconds (60x30, or 30 minutes) without locating // anyone before it automatically powers down. Set to '0' to disable the auto-off function integer TotalNoScansAllowed = 0;
InitialiseObject()
{
Power = FALSE;
PowerText = "On";
ObjectOwner = llGetOwner();
llSetObjectName(ObjectName + Version);
llSetObjectDesc("supplied courtesy of " + Author + "'s " + Supplier);
// set the particle radius to be 0.50m above the prim
vector PrimSize = llGetScale();
Radius = ((PrimSize.z / 2) + (FontSize/2)) + 0.50;
AnnounceWelcome();
StopOperation();
}
AnnounceWelcome()
{
llOwnerSay(
"Thank you for your interest in this " + ObjectName + " "
+ Version + " created by " + Author + " at " + Supplier + ". \nTouch to operate.");
}
MakeMenu()
{
integer CommChannel = (-200000 - ((integer)llFrand(12345) * -1));
ListenChannel = llListen(CommChannel, "", ObjectOwner, "");
llDialog(ObjectOwner, MenuText, MenuItems, CommChannel);
}
StartOperation()
{
WorkChar = "";
NoSensorCounter = 0;
StartSensorCheck();
llOwnerSay( ObjectName + " has been turned ON");
}
StartSensorCheck()
{
// we dont want to use llSensorRepeat, cos it might kick-off a new scan before the previous name has been fully displayed
// llSensor lets us control when we want a scan performing, which is not until after the previous text string has finished
if (FindRandomAV)
{
llSensor("",NULL_KEY, AGENT, Range, ScanArc);
}
else
{
ApplyDefaultText();
}
}
StartParticle(string ParticleChar)
{
llParticleSystem([ PSYS_PART_FLAGS, 0x100, PSYS_SRC_PATTERN, 0x04, PSYS_SRC_TEXTURE, llList2Key(WorkUUIDPalette, llListFindList(WorkCharIndex, (list)ParticleChar)), PSYS_PART_START_SCALE,<FontSize, FontSize, 0.0>, PSYS_PART_END_SCALE,<FontSize, FontSize, 0.0>, PSYS_PART_START_ALPHA,1.0, PSYS_PART_END_ALPHA,1.0, PSYS_PART_MAX_AGE, 30.0, PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RADIUS, Radius, PSYS_SRC_BURST_RATE, LetterTimeGap, PSYS_SRC_MAX_AGE, LetterTimeGap, PSYS_SRC_BURST_SPEED_MIN,0.45, PSYS_SRC_BURST_SPEED_MAX,0.45 ]); }
PrepareData()
{
// make a list index of unique characters
MakeCharIndex();
// make a list containing only the UUID's of the characters we need for this name
MakeTexturePalette();
// start processing the characters
llSetTimerEvent(LetterTimeGap);
}
MakeCharIndex()
{
// loop through WorkDisplayText letter-by-letter, add each unique character to list WorkCharIndex WorkCharIndex = []; integer x; integer y = llStringLength(WorkDisplayText); for (x = 0; x < y; x++) { if (llListFindList(WorkCharIndex, (list)llGetSubString(WorkDisplayText, x, x)) == -1) { WorkCharIndex = WorkCharIndex + (list)llGetSubString(WorkDisplayText, x, x); } } }
MakeTexturePalette()
{
// locate the required texture UUID's in MasterUUIDPalette and extract them out into list WorkUUIDPalette
WorkUUIDPalette = [];
integer x;
integer y = llGetListLength(WorkCharIndex);
for (x = 0; x < y; x++)
{
WorkUUIDPalette = WorkUUIDPalette + (list)llList2Key(MasterUUIDPalette, llListFindList(MasterCharIndex, (list)llList2String(WorkCharIndex,x)));
}
}
ApplyDefaultText()
{
// select & assign a default text string for display, and add a space at the end, turn to upper case
WorkDisplayText = llToUpper(llList2String(DefaultTextPalette, (integer)llFrand((float)llGetListLength(DefaultTextPalette)))) + " ";
// put it all together
PrepareData();
}
SayScanSettings()
{
string MessageLine = "Scans will be performed ";
if (ScanArc == PI) { MessageLine = MessageLine + "360 degrees around the prim"; } else { MessageLine = MessageLine + "forward of the prim's local X-Axis"; } llOwnerSay(MessageLine + " with a range of " + (string)llFloor(Range) + "m."); }
StopOperation()
{
llSetTimerEvent(0.0);
llSensorRemove();
llListenRemove(ListenChannel);
llParticleSystem([]);
}
default
{
on_rez(integer start_param) { // reset on rez llResetScript(); }
changed( integer change )
{
if(change & CHANGED_OWNER )
{
// reset script on change of Owner
llResetScript();
}
}
state_entry()
{
InitialiseObject();
}
touch_start(integer num_detected)
{
key DetectedUser = llDetectedKey(0);
if (DetectedUser == ObjectOwner) { // owner only operation if(Power) { PowerText = "Off"; } else { PowerText = "On"; }
if (FindRandomAV) { // Senor mode & 'SetRange' options are only avaliable if we scanning for random AV's MenuItems = [PowerText, FindRandomAVText, ScanArcText, "SetRange"]; } else { MenuItems = [ PowerText, FindRandomAVText ]; } MenuItems = ["Close", "Help", "ResetScript"] + llListSort(MenuItems,1,TRUE); MenuText = "MAIN MENU: \n- On-Off: toggle power \n- Defaults-Names: toggle display mode \n- XAxis-360 degree: toggle if scan is forward of the prim, or all around it \n- SetRange: set scanner range \n- ResetScript: restore settings \n- Help: Link to product Help page"; MakeMenu(); } else { llInstantMessage(DetectedUser, "Thank you for your interest in this " + ObjectName + " " + Version + " created by " + Author + " at " + Supplier + ". \nYou can get a free copy of this script at http://wiki.secondlife.com/wiki/User:Debbie_Trilling"); } }
sensor(integer total_number)
{
// locate a random AV target
key IntendedTarget = llDetectedKey((integer)llFrand(total_number));
// did we use this AV last time? if so, display a default text string instead
if (IntendedTarget == LastTarget)
{
// we used this AV last time
ApplyDefaultText();
LastTarget = "";
}
else
{
// this is a different AV so populate LastTarget for the check next time around
LastTarget = IntendedTarget;
// determine the first name of the random AV, turn to upper case, add a space to the end & assign to WorkDisplayText
WorkDisplayText = "HI " + llToUpper(llGetSubString(llKey2Name(IntendedTarget), 0, (llSubStringIndex(llKey2Name(IntendedTarget), " ") -1))) + " ";
// put it all together
PrepareData();
}
}
no_sensor()
{
// counts the number of times that the scanner doesn't find anyone in range. If TotalNoScansAllowed is set to greater than zero, automatically powers down the toy
// when the number of no_sensors exceeds TotalNoScansAllowed. However, this functionality is disabled if TotalNoScansAllowed is set to zero.
NoSensorCounter++;
if ((NoSensorCounter > TotalNoScansAllowed) && (TotalNoScansAllowed > 0))
{
StopOperation();
llInstantMessage(ObjectOwner, "\nThe " + ObjectName + " has been automatically switched OFF as no Agents have been detected within the set timeframe.");
}
else
{
ApplyDefaultText();
}
}
timer()
{
// initialise WorkChar. This is the variable we will manipulate as we process the text string
if(WorkChar == "")
{
WorkChar = WorkDisplayText;
}
// fire the first character of the remaining string StartParticle(llGetSubString(WorkChar, 0, 0));
if(llStringLength(WorkChar) == 1) { // this is the space character at the end, so prepare to re-initialise WorkChar = ""; StartSensorCheck(); } else { // remove first character of remaining string, as we've now processed it WorkChar = llGetSubString(WorkChar, 1, -1); } }
listen(integer channel, string name, key id, string message)
{
// listen housekeeping
llListenRemove(ListenChannel);
message = llToLower(message);
// process selection if ((message == "on") || (message == "off")) { // toggle power if (message == "on") { StartOperation(); } else { StopOperation(); llOwnerSay( ObjectName + " has been turned OFF"); } Power = !Power; } else if ((message == "defaults") || (message == "names")) { // toggle display mode if (message == "defaults") { FindRandomAVText = "Names"; llOwnerSay("Particle stream will display default texts only"); } else { FindRandomAVText = "Defaults"; llOwnerSay("Particle stream will display random names and default texts"); } FindRandomAV = !FindRandomAV; } else if ((message == "x-axis") || (message == "360degree")) { // toggle sensor arc mode if (message == "x-axis") { ScanArc = PI_BY_TWO; ScanArcText = "360degree"; } else { ScanArc = PI; ScanArcText = "X-Axis"; } SayScanSettings(); } else if (message == "setrange") { // send Scanner Range Menu MenuText = "SET SCANNER RANGE MENU: Please set the scanner range:"; MenuItems = (list)"Close" + ScannerItems; MakeMenu(); } else if (llListFindList(ScannerItems, (list)message) != -1) { // derive the new range by removing the "m" from the end of 'message' Range = (float)llGetSubString(message, 0, 1); SayScanSettings(); } else if (message == "resetscript") { llOwnerSay("Resetting script. Please wait..."); llResetScript(); } else if (message == "help") { string URL_HELPPAGE = "http://wiki.secondlife.com/wiki/Talk:Random_AV_Particle_Name_Generator"; llLoadURL(ObjectOwner, "This link will take you to the " + ObjectName + "'s Help page.", URL_HELPPAGE); } else if (message == "close") { // let fall thro' } else { llOwnerSay("MAIN MENU: Unrecognised menu selection"); } }
// default end } </lsl>