07-25-2004 13:48
Not much fanfare on this one. Included is a little script to output text over your Av's head in a little word bubble. Simple script, heard it's been done before by Oz Spade and others with prefab textures after I made this - but I figured I'd open the source anyway. :D

CODE
//Opening half of particle generator: Ama Omega particle script
//Chatbox code, word wrap, and just about everything else: Jeffrey Gomez
//Slight modifications and second texture by Chad Street

string texture="chatbox"; //texture applied to the word bubble
vector chatColor=<0,0,0>; //color of displayed text, in RGB
vector bubbleColor=<0,0,1>; //color of displayed bubble, in RGB
string playerName = "Jeffrey Gomez"; //for practical joke purposes.
//Uses channel 124 for synching messages across multiple bubbles. Remove
//this variable if you do not wish to have anyone use it.

// Mask Flags - set to TRUE to enable
integer glow =TRUE; // Make the particles glow
integer bounce = TRUE; // Make particles bounce on Z plan of object
integer interpColor = TRUE; // Go from start to end color
integer interpSize = TRUE; // Go from start to end size
integer wind = FALSE; // Particles effected by wind
integer followSource = FALSE; // Particles follow the source
integer followVel = FALSE; // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_ANGLE;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner
// and "self" will target this object
// or put the key of an object for particles to go to
//key target="self";
key target="";

// Particle paramaters
float age =0.7; //how long will particles live (in seconds)
float maxSpeed = 0; //maximum speed a particle should be moving
float minSpeed = 0; //minimum speed a particle should be movie
float startAlpha =0.3; //alpha transparency at start
float endAlpha =0.3; //alpha at end
//vector startColor = <1,1,1>; //particles start as this color
//vector endColor = <1,1,1>; //and end as thiscolor
vector startSize = <2,1.5,3>; //particles start at this size
vector endSize = <2,1.5,3>; //and end at this size
vector push = <0,0,0>; //how far to push particles

// System paramaters
float rate = .1; // How fast to emit particles
float radius = 0.1; // Radius to emit particles for BURST pattern
integer count =5; // How many particles to emit per BURST
float outerAngle = 0.0; // Outer angle for all ANGLE patterns
float innerAngle = 0.0; // Inner angle for all ANGLE patterns
vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source
float life = 0;



// Script variables
integer flags;

updateParticles()
{
if (target == "owner") target = llGetOwner();
if (target == "self") target = llGetKey();
if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
if (wind) flags = flags | PSYS_PART_WIND_MASK;
if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK;


//llMakeSmoke( 500, 1, 1, 10, 1, "Alien FaceSucker.tga", <0,0,0>);
if (1) { llParticleSystem([ PSYS_PART_MAX_AGE,age,
PSYS_PART_FLAGS,flags,
PSYS_PART_START_COLOR, bubbleColor,
PSYS_PART_END_COLOR, bubbleColor,
PSYS_PART_START_SCALE,startSize,
PSYS_PART_END_SCALE,endSize,
PSYS_SRC_PATTERN, pattern,
PSYS_SRC_BURST_RATE,rate,
PSYS_SRC_ACCEL, push,
PSYS_SRC_BURST_PART_COUNT,count,
PSYS_SRC_BURST_RADIUS,radius,
PSYS_SRC_BURST_SPEED_MIN,minSpeed,
PSYS_SRC_BURST_SPEED_MAX,maxSpeed,
PSYS_SRC_TARGET_KEY,target,
PSYS_SRC_INNERANGLE,innerAngle,
PSYS_SRC_OUTERANGLE,outerAngle,
PSYS_SRC_OMEGA, omega,
PSYS_SRC_MAX_AGE, life,
PSYS_SRC_TEXTURE, texture,
PSYS_PART_START_ALPHA, startAlpha,
PSYS_PART_END_ALPHA, endAlpha
]);
}
}
phaseOut()
{ //Begin phase out and message shutoff.
// startAlpha = 0.1;
// endAlpha = 0.1;
updateParticles();
llSleep(0.2);
startAlpha = 0.05;
endAlpha = 0.05;
updateParticles();
llSleep(0.2);
startAlpha = 0.03;
endAlpha = 0.03;
updateParticles();
llSleep(0.2);
startAlpha = 0.01;
endAlpha = 0.01;
updateParticles();
llParticleSystem([]);
llSetText("",<0,0,0>,1.0);
}
default
{
state_entry()
{
llListen(0,"",llGetOwner(),"");
llListen(1,"",llGetOwner(),"");
if(playerName != "") llListen(124,playerName,"","");
}
attach(key attachedAgent)
{
llResetScript();
}
timer()
{
llSetTimerEvent(0.0);
phaseOut();
}
listen(integer chan, string name, key id, string msg)
{
integer type = llGetAgentInfo(id);
if(type != 0)
{
if(llDeleteSubString(msg, 3,llStringLength(msg)) == "/me")
{
msg = llDeleteSubString(msg, 0, 2);
msg = llKey2Name(llGetOwner()) + msg;
}
if(llStringLength(msg) >= 3 || chan == 1)
{
startAlpha = 0.05;
endAlpha = 0.05;
integer j; //Word wrapping below vvv
integer one;
integer two = llStringLength(msg);
integer three = llStringLength(msg);
integer four = llStringLength(msg);
integer five = llStringLength(msg);
if(llStringLength(msg) >= 24)
{
for(j = 24;j > 14; j--)
{
if(llGetSubString(msg,j,j) == " ")
{
one = j;
j = 0;
}
else if(j==15) one = 24;
}
}
else one = llStringLength(msg);
if(llStringLength(msg) > (one+24))
{
for(j = (one + 24);j > (one + 14); j--)
{
if(llGetSubString(msg,j,j) == " ")
{
two = j;
j = 0;
}
else if(j==one + 15) two = one + 24;
}
}
if(llStringLength(msg) > (two+24))
{
for(j = (two + 24);j > (two + 14); j--)
{
if(llGetSubString(msg,j,j) == " ")
{
three = j;
j = 0;
}
else if(j==two + 15) three = two + 24;
}
}
if(llStringLength(msg) > (three+24))
{
for(j = (three + 24);j > (three + 14); j--)
{
if(llGetSubString(msg,j,j) == " ")
{
four = j;
j = 0;
}
else if(j==three + 15) four = three + 24;
}
}
if(llStringLength(msg) > (four+24))
{
for(j = (four + 24);j > (four + 14); j--)
{
if(llGetSubString(msg,j,j) == " ")
{
five = j;
j = 0;
}
else if(j==four + 15) five = four + 24;
}
if(two > llStringLength(msg)) two = llStringLength(msg);
if(three > llStringLength(msg)) three = llStringLength(msg);
if(four > llStringLength(msg)) four = llStringLength(msg);
if(five > llStringLength(msg)) five = llStringLength(msg);
} //Word wrapping above ^^^
string message1 = llGetSubString(msg,0,one);
if(llStringLength(msg) > (one+1)) one += 1;
string message2 = llGetSubString(msg,one,two);
if(llStringLength(msg) > (two+1)) two += 1;
string message3 = llGetSubString(msg,two,three);
if(llStringLength(msg) > (three+1)) three += 1;
string message4 = llGetSubString(msg,three,four);
if(llStringLength(msg) > (four+1)) four += 1;
string message5 = llGetSubString(msg,four,five);
string message6 = "";
if(llStringLength(msg) > five) message6 = "...";
if(llStringLength(msg) >= 60)
{
startSize = <2,2,3>;
endSize = <2,2,3>;
}
if(llStringLength(msg) >= 40 && llStringLength(msg) <= 59)
{
startSize = <2,1.5,3>;
endSize = <2,1.5,3>;
}
if(llStringLength(msg) <= 24 && llStringLength(msg) >= 6)
{
startSize = <1.5,1.0,3>;
endSize = <1.5,1.0,3>;
}
if(llStringLength(msg) <= 5)
{
startSize = <1,0.75,3>;
endSize = <1,0.75,3>;
}
llParticleSystem([]);
updateParticles();
llSetText(message1 + "\n" + message2 + "\n" + message3 + "\n" + message4 + "\n" + message5 + message6,chatColor,1.0);
llSetTimerEvent(5.0); //Time for the bubble to display
}
}
}
}


Followup: A sample texture for the word box is available here.

Also, a cleaner version of word wrap as written by Chris Omega (not used, but figured I'd post his) -

CODE
string autoWordwrap(integer charsPerLine, string text) {
list words = llParseString2List(text, [" "], []);
integer numWords = llGetListLength(words);
string ret = "";
string curLine = "";
integer i;
for(i = 0; i < numWords; i++) {
string word = llList2String(words, i);
if (llStringLength(word) >= charsPerLine) {
curLine += word + "\n";
ret += curLine;
curLine = "";
} else if (llStringLength(word) + llStringLength(curLine) < charsPerLine) {
curLine += word + " ";
} else {
curLine += "\n";
ret += curLine;
curLine = word + " ";
}
}
ret += curLine;
return ret;
}


I should note I also have freebies of these available on my plot (Landmark included with the actual items), but I'm not too sure about board advertising... so for now, omitted.

Enjoy.:D

PS: If there's sufficient interest, I'll personally comment the bejeezus out of my own code (and ask Chris to do the same with his). For now though, enjoy the free script.