Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

This old script...

Little Ming
The Invisible Man
Join date: 31 Mar 2005
Posts: 84
08-30-2008 14:31
So I've had this old script laying around in my inventory for ages. The guy who made it gave it out for free and doesn't play anymore. I imagine there are better ways of doing a script like this these days, and that is why I am here. With the release of Mono I was wondering if someone would be willing to maybe remake an optimized version of this script?

Either way, here it is, feel free to play with it, but make sure to give the original author some credit for its design.

This is the core script.

From: someone

// Leopards FlexAnimballs

// ToDo: Config notecard loader.
// Proper export of config to email.

integer channel = 0; // Channel to listen on for commands. Set to 0 if you want it public.
vector referencepos = <0,0,0>; //Reference pos, so the entire system is relocateable
list animations = []; // List of animations, "command","animationfilename",<ball position offset to referencepos>,<offset>,<rotation in degrees>,<desc>,<sittext>

// Do net edit below this line.

integer debug_=0;
integer listener=0;
integer anim;
key sitAgent = NULL_KEY;
integer gotPermission = FALSE;
string lastanim="sit";
string nextanim;
integer listparamlen=6; // Number of parameters per hotspot - 1
integer configline=0;
integer editmode=0;
integer lisths=0;
integer x; //General loop variable

debug(string message)
{
if (debug_ == 1)
{
llSay(0,"DEBUG: " + message);
}
}
reply(string message)
{
llSay(0,message);
}
default
{
state_entry()
{
llGetNotecardLine("fabconfig",configline);
configline++;
}
on_rez(integer start_param)
{
llResetScript();
}
dataserver(key query_id,string data)
{
if (data != EOF)
{
if (configline==1)
{
channel=(integer)data;
}
if (configline==2)
{
referencepos=(vector)data;
if (referencepos==<0,0,0>;)
{
llInstantMessage(llGetOwner(),"You did not set a reference position in the config file. Please see the help file for more info about reference positions. The current location will be used as temporary reference position.";);
referencepos=llGetPos();
}
}
if (configline >=3)
{
if (llStringLength(data) >= 5) // Make sure we only get non-empty lines)
{
debug("Read hotspot: "+(string)llCSV2List(data));
list mydata=llCSV2List(data);
animations += (string)llList2String(mydata,0);
animations += (string)llList2String(mydata,1);
animations += (vector)llList2String(mydata,2);
animations += (vector)llList2String(mydata,3);
animations += (string)llList2String(mydata,4);
animations += (string)llList2String(mydata,5);
animations += (integer)llList2String(mydata,6);
}
}
llGetNotecardLine("fabconfig",configline);
configline++;
} else
{
state running;
}
}
}
state running
{
state_entry()
{
llSitTarget(<0,0,-0.1>,ZERO_ROTATION);
llListenRemove(listener);
listener = llListen(channel,"",NULL_KEY,"";);
nextanim = "";
llSetPos(referencepos);
llSetRot(ZERO_ROTATION);
llSetAlpha(1.0,ALL_SIDES);
llInstantMessage(llGetOwner(),"Touch the ball to get info.";);
}
on_rez(integer start_param)
{
llResetScript();
}
listen(integer channel, string name, key id, string message)
{
list params = llParseString2List(message,[","],[]);
string cmd=llToLower(llList2String(params,0));
if (cmd=="fabshow";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
llSetAlpha(1.0,ALL_SIDES);
}
if (cmd=="fabhide";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
llSetAlpha(0.0,ALL_SIDES);
}
if (cmd=="fabedit";)
{
editmode=1;
llSetTimerEvent(20.0);
reply("Touch the animball within 20 seconds to engage the edit mode.";);
return;
}
if (cmd=="fabeditend";)
{
if (editmode==2)
{
reply("Edit mode ended.";);
}
editmode=0;
return;
}
if (cmd=="fabgetcurpos";)
{
if (editmode != 2)
{
return;
}
reply("Current Position: "+(string)llGetPos());
reply("Current Rotation: "+(string)(llRot2Euler(llGetRot())*RAD_TO_DEG));
reply("Offset to refpos: "+(string)(llGetPos() - referencepos));
}
if (cmd=="fabgetrefpos";)
{
if (editmode != 2)
{
return;
}
reply("Current Reference Position: "+(string)referencepos);
}
if (cmd=="fabsetrefpos";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
referencepos = llGetPos();
reply("New reference position set to "+(string)referencepos);
}
if (cmd=="fabgotorefpos";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
reply("Moving to reference position.";);
llSetPos(referencepos);
}
if (cmd=="fablisths";)
{
reply("Please touch the ball of which you want to get the list of hotspots within 20 seconds.";);
lisths=1;
llSetTimerEvent(20.0);
}
if (cmd=="fabstatus";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
reply(" Lastanim:" + lastanim);
reply(" Nextanim:" + nextanim);
}
if (cmd=="fabdelhs";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
if (llGetListLength(params) != 2)
{
reply("You must specify a command to delete, e.g. 'fabdelhs,/command1'";);
} else
{
anim = llListFindList(animations,[llList2String(params,1)]);
if (anim == -1)
{
reply("The given command does not exist. Commands are case sensitive, btw.";);
} else
{
animations = llDeleteSubList(animations,anim,anim + listparamlen);
reply("Animation hotspot "+llList2String(params,1)+" deleted. Please save to get the updated config via mail.";);
}
}
}
if (cmd=="fabaddhs";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
if (llGetListLength(params) != 6)
{
reply("Invalid number of parameters. Useage: 'fabaddhs,command,animationname,desc,sittext,owneronly(0 or 1)'";);
} else
{
if (llListFindList(animations,[llList2String(params,1)]) != -1)
{
reply("That command already exists. Please delete it first or choose another name.";);
} else
{
animations += [llList2String(params,1),llList2String(params,2),llGetPos() - referencepos,llRot2Euler(llGetRot()) * RAD_TO_DEG,llList2String(params,3),llList2String(params,4),llList2Integer(params,5)];
reply("New animation hotspot "+llList2String(params,1)+" added. Please save to get the updated notecard config via mail.";);
}
}
}
if (cmd=="fabsave";)
{
if (editmode != 2)
{
return;
}
if (id != llGetOwner())
{
reply("Only "+llKey2Name(llGetOwner())+" can use this function.";);
return;
}
if (llGetListLength(params) != 2)
{
reply("You must specify an e-mail adress as parameter. E.g. 'fabsave,foo@test.com'";);
} else
{
string mailbody="----- Please copy everything below this line to the fabconfig notecard! ------\n";
mailbody += (string)channel + "\n";
mailbody += (string)referencepos + "\n";
for (x=0;x<llGetListLength(animations);x=x+listparamlen+1)
{
mailbody += llList2CSV(llList2List(animations,x,x+listparamlen))+"\n";
}
reply("Sending configuration.";);
llEmail(llList2String(params,1),"Config for "+llGetObjectName(),mailbody);
reply("Configuration was sent.";);
}
}
if (cmd=="fabreset";)
{
if (editmode != 2)
{
return;
}
reply("Resetting...";);
llResetScript();
}
if (cmd=="fabanim";)
{
if (editmode != 2)
{
return;
}
if (llGetListLength(params) != 2)
{
reply("You must specify an animation to run, e.g. fabanim,cuddle1";);
return;
}
nextanim=llList2String(params,1);
if (sitAgent != NULL_KEY)
{
llRequestPermissions(sitAgent,PERMISSION_TRIGGER_ANIMATION);
} else
{
reply("There must be someone sitting on the animball to make this work.";);
}
}
anim=llListFindList(animations,[message]);
if (((anim%(listparamlen+1)) != 0) && (anim != 0))
{
return;
}
if (anim != -1)
{
debug("Found animation "+llList2String(animations,anim+1));
debug(" Position: "+(string)llList2Vector(animations,anim+2));
debug(" Rotation: "+(string)llList2Vector(animations,anim+3));
debug(" Desc: "+llList2String(animations,anim+4));
debug(" SitText: "+llList2String(animations,anim+5));
debug(" Owner: "+(string)llList2Integer(animations,anim+6));
if ((llList2Integer(animations,anim+6) != TRUE) || (id == llGetOwner()))
{
llSetSitText(llList2String(animations,anim+5));
llSetPos(referencepos+llList2Vector(animations,anim+2));
llSetRot(llEuler2Rot(llList2Vector(animations,anim+3)*DEG_TO_RAD));
nextanim=llList2String(animations,anim+1);
if (sitAgent != NULL_KEY)
{
llRequestPermissions(sitAgent,PERMISSION_TRIGGER_ANIMATION);
} else
{
lastanim="sit";
}
} else
{
reply("Only "+llKey2Name(llGetOwner())+" can select this hotspot.";);
}
}
}
changed(integer change) {
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if ( sitAgent == NULL_KEY && agent != NULL_KEY ) {
sitAgent = agent;
llSetTimerEvent(0.0);
llRequestPermissions(sitAgent,PERMISSION_TRIGGER_ANIMATION);
llSetAlpha(0.0,ALL_SIDES);
}
else if ( sitAgent != NULL_KEY && agent == NULL_KEY) {
if ( gotPermission )
llStopAnimation(lastanim);
lastanim = "sit";
sitAgent = NULL_KEY;
gotPermission = FALSE;
llSetAlpha(1.0,ALL_SIDES);
llSetTimerEvent(5*60.0);
}
}
}
run_time_permissions(integer parm) {
if(parm == PERMISSION_TRIGGER_ANIMATION) {
gotPermission = TRUE;
if (llStringLength(lastanim) >= 1)
{
llStopAnimation(lastanim);
} else
{
llStopAnimation("sit";);
}
if (llStringLength(nextanim) >= 1)
{
llStartAnimation(nextanim);
}
lastanim=nextanim;
}
}
timer()
{
if (editmode==1)
{
editmode=0;
llSetTimerEvent(0.0);
return;
}
if (lisths==1)
{
lisths=0;
llSetTimerEvent(0.0);
return;
}
llSetPos(referencepos);
llSetRot(ZERO_ROTATION);
llSetAlpha(1.0,ALL_SIDES);
lastanim="sit";
nextanim="";
llSetTimerEvent(0.0);
}
touch_start(integer num_detected)
{
if (editmode == 1)
{
llSetTimerEvent(0.0);
editmode=2;
reply("Edit mode engaged. You can now use all commands.";);
return;
}
if (lisths == 1)
{
llSetTimerEvent(0.0);
lisths=0;
reply("List of available hotspots:";);
for (x=0;x<llGetListLength(animations);x=x+listparamlen+1)
{
reply(" Command "+llList2String(animations,x)+" with animation "+llList2String(animations,x+1)+": "+llList2String(animations,x+4));
}
return;
}
llGiveInventory(llDetectedKey(0),"Flexible Animball Help";); // Give the help.
}
}



Create a notecard named "fabconfig" and after following the instructions and configuring the poseball, take the email readout and copy/paste it into this notecard.

Here is the help doc to help with understanding its use.

From: someone

Script Kitty Productions (SKiP) Proudly Present

Flexible Animball

Done in Dec. 2004 by Leopard Loveless.

Disclaimer:
This item is free and it or modified versions of it must not be resold for money.
If you paid for this, you have been thoroughly fooled.
If you like this item and can spare some Linden Dollars, I'd be happy if you toss some my (Leopard Loveless) way.
If you modify this script and pass it on (For free, mind you!), please give me credit and let me have a copy, if you can.

Version History:
1.0 - First stable release
1.1 - Fixed a problem in the config loader that caused offsets and rotations to be interpreted incorrectly
Put the default reference position to <0,0,0>. The animball will now write a warning until the reference is set and
will assume the current location it's rezzed at as the temporary reference position.
The animball will return to the reference position 5 minutes after an avatar dropped off.
Added command "fabanim".

About:
The basic idea behind the Flexible Animballs is to save prims and spare the users the distress to hop off one animball and jump on another to change positions during a dance, cuddling or the more hot kinds of animated situations.
The normal household features tons of animballs, but only very few of them are used simultanously.
The idea behind the Flexible Animballs is that they change the animation, location and rotation of the one that sits on them on a simple command. You can have multiple Animballs react to the same commands, but have different locations, so you can position as many of the balls as you like with just one command.
Imagine: You have two Flexible Animballs on your veranda. You hop on them, it's a slow dance for you and your partner. You dance a bit, and you decide it's time for maybe a little hug. The normal way would be to step off the animballs, and use a hug animator or some other animballs.. with the Flexible Animballs all you have to do is maybe say "/hugs".. if both balls know this command (meaning you taught it in before), both balls will relocate to a new location, rotate right for the animation and start the hug animation. Then you maybe thing it's time for a kiss. Good. Type "/kiss", for example. Then "/cuddle", "/foreplay", "/......" .. .you get the idea. Or just change dances.. from one dance to the other. Works the same way. Or poses, seating positions.. whatever you can imagine. It's that easy. And just as few prims as you need animated persons at the same time simultanously.

Functions:
Functions marked with an asterisk (*) are owner only functions.
Please note that these commands only work after you started the edit mode with "fabedit" and then touched the ball.
To end the edit mode, use "fabend".

fabshow(*):
No arguments.
Makes the animball visible.

fabhide(*):
No arguments.
Makes the animball invisible.

fabgetcurpos:
No arguments.
Returns the current location of the animation ball. For debug purposes mainly or if you want
to set up the config file manually instead of using the functions fabaddhs and fabsave.

fabgetrefpos:
No arguments.
Returns the reference position of the animation ball. For debug purposes mainly.

fabsetrefpos(*):
No arguments.
Sets the reference position of the animball to the current location.
Note that this causes ALL Hotspots to be at a new location, too, as they are stored as
offsets from this reference position. Please use fabsave to get the updated
config and set it permanently in the config file.

fabgotorefpos(*):
No arguments.
Moves the animball to the reference position. For debug purposes mainly.

fablisths:
No arguments.
Lists all currently known animation hotspots.

fabstatus(*):
No arguments.
Returns some debug information.

fabdelhs(*):
Parameter1: Name/command of the Hotspot to delete.
Deletes the named hotspot from the animball. Please use fabsave to get the updated
config and set it permanently in the config file.

fabaddhs(*):
Parameter1: Name/Command of the hotspot to add, e.g. /poolkissing. Case sensitive!
Parameter2: Name of the animation file to use inside the animball. Case sensitive!
Parameter3: Description of the hotspot. This will be shown in fablisths.
Parameter4: Text to show in the radial menu when someone rightclicks the ball while at this hotspot.
Parameter5: Owner Lock. If 0, everyone can send the animball to this hotspot, if 1, only the owner can.
Adds a new hotspot to the config. Please use fabsave to get the updated
config and set it permanently in the config file.

fabsave(*):
Parameter1: e-mail adress to send the config to, e.g. [email]foo@test.com[/email]
Sends the current config to the given e-mail address so you have a backup and so you can easily copy
the config from there and put it into the configuration file.

fabanim:
Parameter1: Name of the animation file inside the animball to run. Case sensitive.
Starts the given animation on the avatar currently sittin on the animball. Useful for starting an anim
before positioning the animball for a new hotspot.

fabreset:
No arguments.
Resets the animball, in case it went weird. It also forces the script to reload the configuration
which might be useful after a change.

Configuration:
Inside the animball you will find a notecard called "fabconfig". This notecard contains the configuration
about all the hotspots and the command channel to listen on.
You will get the text to put there by using the fabsave command. Just copy the content of the e-mail you
will get to the config file and hit save.
The format of this config file is as follows:
1. Line: Just one number: The command channel the animball listens to (Default:0).
If you change this, the animball will listen at different channels. All commands issued to it will then not be
visible in public anymore. The commands need to be prefixed with the channel, then.. e.g. /22fabreset.
All hotspot names will need this prefix, then, too.. if you have a hotspot named "test", the command to
trigger it would then me "/22test". If the channel is 0, the prefix is not needed and the commands are shown
in public.
2. Line: <x,y,z> The reference position. Should be somewhere in your house. If you ever move, all you have to change
is the reference position, as all hotspots are saved relative to this position.
THIS IS THE PARAMETER THAT YOU NEED TO SET BEFORE YOU SET UP ANY HOTSPOTS!
All further lines:
Information about the hotspot locations. Format as follows:
Command,AnimationFileName,<x,y,z>;(offset to the reference position),<rx,ry,ry>;(Rotation of the anim, in degrees (0..359),Description,RadialMenuDisplayText,OwnerOnly(can be 0 or 1)

Hotspots
I call a location with it's animation attached to it a hotspot. You can have as many hotspots as you like throughout
your land. A hotspot consists of the uniqe command, the name of the animation file, the offset to the reference
position, the rotation of the animball, it's description, the sit text for the right click menu and either a 0 or 1 which
tells the ball if it's a hotspot that can only be triggered by the owner (1) or all people around (0).

Reference Position:
All hotspots will be saved relative to the reference position. This is the first setup you should make. Pick a nice spot
on your land and use fabsetrefpos, then save config and put it into the animball before continuing.
The reason why I use a reference position is simple: Imagine you move your house to another location. If I had used
absolute positions in the sim, you'd have to change all hotspots you had to be at the new locations. To prevent this
I made them relative to a position you can configure, named the reference position. You just set the new reference
position to the same spot where it was before in your house (so pick a spot you can easily remember) and you're done
moving. All hotspots will then use the new reference position as base, and will appear at the same position like they
were before. Mind you, tho, if you _rotate_ your house, you _will_ have to redo the reference positions, still.

Multiple Animballs:
If you have several of these balls, it might be a good idea to set them to different channels for the hotspot
setup process, else the balls will get confused which of them you adress with your commands. When it's all set up
you can change the channel back in the config file so both react to the same commands, but have different hotspot
locations and anims stored for the given commands. This way you can archieve nice couple dances, hug animations,
sexual positions and much more.

Getting help:
If you have any questions or problems with the Flexible Animballs, or you have any feature suggestions for a later
version, please don't hesitate to send me (Leopard Loveless) an IM. I live in europe, so I am online at times that
might not match your time zone, but I will reply as soon as I get the message.
Please make sure you have read this help file and probably asked friends that set up a flexible animball before prior
to asking me for assistance, tho, else I fear I get swampled in requests, as this animball is nice, but can be quite
complicated despite my effords to make it as simple to use as possible.
Also please be nice when you have a question, else I reserve the right to choose to not answer. I give this item
out for free, after all.

Credits:
Code - Leopard Loveless
Documentation - Leopard Loveless
Testing - shinmai Akebono,Moonstone Stormwind, Cade Stirling
Attica Bekkers
Registered User
Join date: 12 Apr 2007
Posts: 28
09-05-2008 22:34
Thankyou for posting this. Im lokoing forward to trying it!
Osgeld Barmy
Registered User
Join date: 22 Mar 2005
Posts: 3,336
09-05-2008 22:37
i just cried alittle looking at that

yes there is better ways to do it ... if someone doesnt do it before i get my video card back (gah still waiting) ill take a whack at it
Little Ming
The Invisible Man
Join date: 31 Mar 2005
Posts: 84
09-07-2008 19:54
From: Osgeld Barmy
i just cried alittle looking at that

yes there is better ways to do it ... if someone doesnt do it before i get my video card back (gah still waiting) ill take a whack at it


Hehe thanks, the script was written by a friend about 3 years ago, so I figured it could use a overhaul...