Blau’s Full-Perm Scripts

These are scripts I’ve written over the years that I think y’all would benefit from, so I’ve made them full-perm / free-use.



Animesh Animator

This is an extremely simple animesh animator script that I wrote to animate some animesh dummies for Kinzart. It’s very to-the-point - but I thought y’all could get some mileage out of it too!

THIS SCRIPT REQUIRES SOME MANUAL SETUP AND SOME MODDING / EDIT MENU SKILLS.

First, you need the thing you want to make an animesh dummy for. This is intended to work with full-mesh things, like the KZK Direwolf or Kritter Sergal, both things I’ve used this script for.

NOTE: If your thing uses Bakes-on-Mesh, do note that Animesh doesn’t support Bakes-on-Mesh and you will need to provide flat uploaded textures.

Rez out all of the body parts you want on your animesh dummy. Rez out a plain plywood cube. Shift-select all of your body parts, THEN select the plywood cube, then Link them together.

With this new object selected, go into Features in the Edit menu, then hit Animated Mesh. Your body parts should snap together and look like a normal avatar.

(If you’re down for a bit more in-depth modification: Remove any extra parts that won’t be visible on your animesh dummy. This could include extra fluff, alternate parts, and so on. This will help save on land impact - rezzed out animesh uses a LOT of land impact!)

Second, you’ll need to get yourself some animations compatible with whatever you’re making an animesh dummy of.

For the Direwolves, I used animations from their built in AOs. For the Kritter Sergals, which are more compatible with “humanoid” animations, I used animations from the Head and Tail AOs to animate those and then used some AO animations from Oracul as the primary stand.

You will almost certainly need multiple animations if you’re kitbashing this - using the Kritter Sergal as an example again, I needed not only a standing animation, but also the brow, mouth, tongue, ear, and tail animations. (If you’re making a custom animation, or you know the animation you’re using controls everything you need, you can get by with just the one.)

I recommend using COPY animations, as you’ll be putting them in the object’s inventory for this method. (You can also play animations with an animation’s key if you happen to have that - I’ll add an alternate version that supports this soon)

Now, the script. It’s commented with an explanation of each part; I’ll go over them again in a moment. You can copy-paste this into a New Script in your inventory for now, and modify it as we go.

Blau's Animesh Animator Script

// Simple Animesh Animation // by Blau Rascon // // Originally written in 2019 to animate the // Direwolf animesh dummies for Kinzart Kreetures // // This script requires some manual setup! // Don't worry, it's not too bad // ///////////////////////////////// // First: Get yourself some animations that work // with whatever you're trying to animate // For the Direwolves I used animations from the // built in AOs to make sure they worked properly // For the Kritter Sergal I used anims from the // head and tail AOs, and most of the standing // animations were from Oracul AOs // ///////////////////////////////// // Strings: These are your animation names // Copy and paste the "string line" // for however many animations you need // to make your animesh work // (e.g. stand, tail, hand, ear, facial animations) // Change "stand" to a useful label for that anim // Change "ANIMATION NAME HERE" to be the inventory name // of the animation string stand = "ANIMATION NAME HERE"; ///////////////////////////////// // Functions: This part makes the animations play // Copy and paste the llStartObjectAnimation line // like you did above, for each animation // you need to make your animesh work // Change "stand" to the matching label // from the strings above init() { llStartObjectAnimation(stand); } ///////////////////////////////// // You don't need to change anything below here // All it does is tell the script to, when it starts, // call the "init" function above to play animations default { state_entry() { init(); } }

The first part, global variables. These hold the names of the animations you’re using. You will need to copy and paste this section for as many animations you are using; for example, if you’re using 4 animations, you need 4 string lines.

Change stand on your animations to be whatever name is most descriptive for that animation, so you know the purpose of that animation. For an animation controlling the tail, you could change stand to tail.

Change "ANIMATION NAME HERE" to the name of the animation for that slot. (Keep the quotations, those mark it as a string! The script will not compile if you remove them.)

The second part, the function that plays the animations. Again, you will need to copy and paste the llStartObjectAnimation(stand); line for as many animations as you have.

Change stand on each copy to match the animations from the global variable section.

The third part just tells the script that, as soon as it starts running, run the init(); function, which plays the animations. You don’t need to change anything down here.

Now, to put it all together:

Drag and drop your chosen animations into the plywood cube of your animesh dummy.

Drag and drop the modified script into the plywood cube.

Your animesh dummy should start animating (you may need to close the Edit menu / de-select it).

You can change animations while the script is in the animesh dummy - drop in the new animation, open the script, change the appropriate animation name, and save. It should update the animation as soon as the script starts back up.

If something gets super weird, I’ve found that toggling Animated Object on and off again tends to fix things.


Modded Script: XyText CasperVend Price Display

This is an XyText script I modified to use the CasperVend vendor API to display the currently displayed product’s price as XyText attached to the vendor.

The original XyText v2 script was written by j4mes Toshi / Aeroson, based on XyText 1.5, which can be viewed here: https://wiki.secondlife.com/wiki/XyText_1.5

For more information on the CasperVend API, please check here: https://wiki.casperdns.com/index.php/CasperVend_2/API

You will need an XyText compatible mesh prim to use this script. I have tested this one, and it worked just fine, though with slight modification to the script, detailed more below. https://marketplace.secondlife.com/p/5-Face-Mesh-Display-free-fullperm/4571354

Now, the script. Copy and paste this into a New Script in your inventory. The script is commented, but I’ll go over what everything does again in a moment.

XyText v2 (Caspervend Price Label v2, rad edit)

/* Caspervend 2 Price Display XyText Script Modification by Blau Rascon Listens for the price of the currently displayed product and displays it as XyText Caspervend API information from here: https://wiki.casperdns.com/index.php/CasperVend_2/API */ /* To use: Link to a Caspervend 2 vendor. Make sure the Vendor is the last selected object (root prim). DO NOT SET THIS PANEL TO THE ROOT PRIM THE VENDORS GET REALLY UPSET AND WILL NOT WORK */ /* FURTHER EDIT: For use with MartinRJ Fayray's 8 Face Mesh Display Changed the texture rotation float to the equivalent of 270 degrees, because otherwise the textures are rotated weirdly This change is marked in the XyText code below, change it from 4.712389 to 0 if you're using a different 8-face mesh prim and things look rotated incorrectly */ string gProdPrice; // variable that holds the price for sending to the xytext machine /*======================================================================================================*/ /*======== START of ===================== XyText v2 for 8 faced mesh ================================*/ /*======================================================================================================*/ /* by j4mes toshi / aeroson */ /* original at http://wiki.secondlife.com/wiki/XyText_1.5 */ list XYTEXT_characterGrid=["00e9f9f7-0669-181c-c192-7f8e67678c8d","347a5cb6-0031-7ec0-2fcf-f298eebf3c0e","4e7e689e-37f1-9eca-8596-a958bbd23963","19ea9c21-67ba-8f6f-99db-573b1b877eb1","dde7b412-cda1-652f-6fc2-73f4641f96e1","af6fa3bb-3a6c-9c4f-4bf5-d1c126c830da","a201d3a2-364b-43b6-8686-5881c0f82a94","b674dec8-fead-99e5-c28d-2db8e4c51540","366e05f3-be6b-e5cf-c33b-731dff649caa","75c4925c-0427-dc0c-c71c-e28674ff4d27","dcbe166b-6a97-efb2-fc8e-e5bc6a8b1be6","0dca2feb-fc66-a762-db85-89026a4ecd68","a0fca76f-503a-946b-9336-0a918e886f7a","67fb375d-89a1-5a4f-8c7a-0cd1c066ffc4","300470b2-da34-5470-074c-1b8464ca050c","d1f8e91c-ce2b-d85e-2120-930d3b630946","2a190e44-7b29-dadb-0bff-c31adaf5a170","75d55e71-f6f8-9835-e746-a45f189f30a1","300fac33-2b30-3da3-26bc-e2d70428ec19","0747c776-011a-53ce-13ee-8b5bb9e87c1e","85a855c3-a94f-01ca-33e0-7dde92e727e2","cbc1dab2-2d61-2986-1949-7a5235c954e1","f7aef047-f266-9596-16df-641010edd8e1","4c34ebf7-e5e1-2e1a-579f-e224d9d5e71b","4a69e98c-26a5-ad05-e92e-b5b906ad9ef9","462a9226-2a97-91ac-2d89-57ab33334b78","20b24b3a-8c57-82ee-c6ed-555003f5dbcd","9b481daa-9ea8-a9fa-1ee4-ab9a0d38e217","c231dbdc-c842-15b0-7aa6-6da14745cfdc","c97e3cbb-c9a3-45df-a0ae-955c1f4bf9cf","f1e7d030-ff80-a242-cb69-f6951d4eae3b","ed32d6c4-d733-c0f1-f242-6df1d222220d","88f96a30-dccf-9b20-31ef-da0dfeb23c72","252f2595-58b8-4bcc-6515-fa274d0cfb65","f2838c4f-de80-cced-dff8-195dfdf36b2c","cc2594fe-add2-a3df-cdb3-a61711badf53","e0ce2972-da00-955c-129e-3289b3676776","3e0d336d-321f-ddfa-5c1b-e26131766f6a","d43b1dc4-6b51-76a7-8b90-38865b82bf06","06d16cbb-1868-fd1d-5c93-eae42164a37d","dd5d98cf-273e-3fd0-f030-48be58ee3a0b","0e47c89e-de4a-6233-a2da-cb852aad1b00","fb9c4a55-0e13-495b-25c4-f0b459dc06de","e3ce8def-312c-735b-0e48-018b6799c883","2f713216-4e71-d123-03ed-9c8554710c6b","4a417d8a-1f4f-404b-9783-6672f8527911","ca5e21ec-5b20-5909-4c31-3f90d7316b33","06a4fcc3-e1c4-296d-8817-01f88fbd7367","130ac084-6f3c-95de-b5b6-d25c80703474","59d540a0-ae9d-3606-5ae0-4f2842b64cfa","8612ae9a-f53c-5bf4-2899-8174d7abc4fd","12467401-e979-2c49-34e0-6ac761542797","d53c3eaa-0404-3860-0675-3e375596c3e3","9f5b26bd-81d3-b25e-62fe-5b671d1e3e79","f57f0b64-a050-d617-ee00-c8e9e3adc9cb","beff166a-f5f3-f05e-e020-98f2b00e27ed","02278a65-94ba-6d5e-0d2b-93f2e4f4bf70","a707197d-449e-5b58-846c-0c850c61f9d6","021d4b1a-9503-a44f-ee2b-976eb5d80e68","0ae2ffae-7265-524d-cb76-c2b691992706","f6e41cf2-1104-bd0b-0190-dffad1bac813","2b4bb15e-956d-56ae-69f5-d26a20de0ce7","f816da2c-51f1-612a-2029-a542db7db882","345fea05-c7be-465c-409f-9dcb3bd2aa07","b3017e02-c063-5185-acd5-1ef5f9d79b89","4dcff365-1971-3c2b-d73c-77e1dc54242a"]; string XYTEXT_characterIndex=" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; vector XYTEXT_getGridPos(string str, integer index) { integer index1=llSubStringIndex(XYTEXT_characterIndex, llGetSubString(str, index, index)); integer index2=llSubStringIndex(XYTEXT_characterIndex, llGetSubString(str, index+1, index+1)); /*There are two ways to use the lookup table...*/ integer Col; integer Row; if (index1 >= index2) { /*In this case, the row is the index of the first character:*/ Row = index1; /*And the col is the index of the second character (x2)*/ Col = index2 * 2; } else {/*Index1 < Index2*/ /*In this case, the row is the index of the second character:*/ Row = index2; /*And the col is the index of the first character, x2, offset by 1.*/ Col = index1 * 2 + 1; } return <Col, Row, 0>; } string XYTEXT_getGridTexture(vector grid_pos) { /*Calculate the texture in the grid to use.*/ integer GridCol = llRound(grid_pos.x) / 20; integer GridRow = llRound(grid_pos.y) / 10; /*Lookup the texture.*/ key Texture = llList2Key(XYTEXT_characterGrid, GridRow * (GridRow + 1) / 2 + GridCol); return Texture; } vector XYTEXT_getGridOffset(vector grid_pos) { /*Zoom in on the texture showing our character pair.*/ integer Col = llRound(grid_pos.x) % 20; integer Row = llRound(grid_pos.y) % 10; /*Return the offset in the texture.*/ return <-0.45 + 0.05 * Col, 0.45 - 0.1 * Row, 0.0>; } renderString(string str) { integer face=0; while(face<8) { vector gridPos=XYTEXT_getGridPos(str,face*2); llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,face,XYTEXT_getGridTexture(gridPos),<1./10,1./10,0>,XYTEXT_getGridOffset(gridPos),4.712389]); // change the last number to 0 if text looks rotated wrong ++face; } } /*======================================================================================================*/ /*======== END of ======================= XyText v2 for 8 faced mesh ================================*/ /*======================================================================================================*/ default { link_message(integer sender, integer num, string str, key id) { if(llGetSubString((string)num, 0, 0) != "-") // Price is stored in linkmessage section "num" which is also used for other information // First we check to see if the "num" message starts with a -, if it does, ignore it // because that isn't a price, it's other data { gProdPrice = (string)num+"L$"; renderString(gProdPrice); // Set the gProdPrice variable to the screened num message // then run the XyText code to display the price on the prim } } }

I added one global variable: string gProdPrice;. This holds the value that the XyText will be set to.

The meat of the script handles XyText rendering. In honesty, I haven’t really looked into how this works, but it’s well commented and the XyText wiki page linked above has some more information. In any case, you don’t need to adjust anything here, unless you’re changing the radians rotation under llSetLinkPrimitiveParamsFast towards the end. (I modified it to fit with the above linked XyText mesh - if you’re using your own, you may need to adjust this value. SL uses Radians and not Degrees.)

After the end of the XyText code, the script checks to see if any link messages have been sent. If so, grab the num part of that message (a number) and check to see if it starts with a dash. If it does, discard it - CasperVend API uses positive numbers to send price information and negative numbers to send other vendor status information, so we only need the positive numbers. Then, set gProdPrice to this new number, with L$ at the end. Finally, pass that new variable to the XyText generator function to update the display.

Now, to use this:

Rez out your XyText mesh prim. Rez out the CasperVend vendor you wish to put the price label on. Give it a moment to boot.

Using the Edit menu, adjust the size and position of the XyText mesh prim to roughly where you want it. The text will start at the left-most square. You can adjust this more later if you need.

Drag and drop this script into the XyText prim. Nothing will happen at first because there is no information to display yet.

In Edit mode, select the XyText prim, THEN select the CasperVend vendor. Link them together and give the vendor a moment to reboot. (Make sure the CasperVend vendor is the last thing you select before you link, otherwise the vendor script will panic when it tries to reboot!)

Once the vendor is done booting and a product is displayed, the XyText should update to show the product’s price. Scrolling items will update the XyText with the selected product’s price.

If you need to adjust the position of your XyText label, use Edit Linked Parts to move just that prim around.


Description to Local Chat

This is a super fast one I put together for use in my HUDs. It reads the description of the prim the script is in, then sends that description to the object owner.

I wrote these to give links to my Marketplace and Update Group. It’ll work with regular links and URI links (the ones that start with secondlife:///app/)

First, copy and paste the script here into a New Script into your inventory:

[Eldritch Cat] Description to Owner Chat

string sDesc; string sSayMe; default { state_entry() { sSayMe = llList2String(llGetLinkPrimitiveParams(LINK_THIS, [ PRIM_DESC ]), 0); } touch_start(integer total_number) { llOwnerSay("Click this to join the group: " + sSayMe); } }

Change the Click this to join the group: text to whatever you want, but be sure to leave a space at the end.

In the prim you’re going to put this in, put the link or URI into the prim’s Description field.

Drag and drop this script into the prim, then click it to test.