Basically, this simplifies avie placement when using PrimParams without a poseball. Sometimes it's a headache figuring out the rotation and position when the prim is rotated oddly, so this script let's you move and rotate the avie in real time, then hard-code the final vectors into the sitscript.
Basic instuctions: place the generic sitscript and the positioner script into the object. Sit on the object and use the movement keys to position the avie. Use the touch menu to report the new offsets, then paste these vectors into the sit script. Then delete the positioner script. The touch menu also changes the movement coordinates, and movement rate.
Generic SitScript:
CODE
//This script was written by Katherine Taney, it is free to use, modify, give away, etc....
//Please give credit and stuffs, stealing is wrong and bad and stuffs....
InitUserVariables() {
//---START USER VARIABLES---\\
//Enter values from pistioner script here -->
SIT_POSITION = (vector) <0,0,0>;//position relative to the poseball
SIT_ROTATION = (vector) <0,0,0>; //Edit this, rotation in degree
//<---
SIT_CAMERA_POSITION = (vector) <0, 0, 0>;//where the camera is at, in local coords
SIT_CAMERA_FOCUS = (vector) <0, 0, 0>;//where the camera is looking at, in local coords
SIT_TEXT = (string) "";//text to hover above poseball--Set to "*" for debug text--Set to "" for blank
SIT_TEXT_COLOR = (vector) <1.0, 0.0, 1.0>; //Color R,G,B
SIT_TEXT_ALPHA = (float) 0.0;//alpha of sit text
SIT_TEXT_HIDEONSIT = (integer) TRUE;//Hide sit text when avie sits TRUE or FALSE
HIDE_POSEBALL_ON_SIT = (integer) FALSE;//Hide the poseball when avie sits on it, TRUE or FALSE
VERBOSE = (integer) FALSE; //Says a bunch of stuff about animation found and stuffs
//---END USER VARIABLES---\\
}
string ANIMATION = "sit_ground";
vector SIT_POSITION;
vector SIT_ROTATION;
string SIT_TEXT;
vector SIT_TEXT_COLOR;
float SIT_TEXT_ALPHA;
vector SIT_CAMERA_POSITION;
vector SIT_CAMERA_FOCUS;
integer SIT_TEXT_HIDEONSIT;
integer HIDE_POSEBALL_ON_SIT;
integer VERBOSE;
integer gAvieNum = -1;
key gAvieKey;
SetAnim()
{
integer cnt = llGetInventoryNumber(INVENTORY_ANIMATION);
if (cnt == 0) ANIMATION = "sit_ground";
else {
ANIMATION = llGetInventoryName(INVENTORY_ANIMATION, 0);
if (VERBOSE) llOwnerSay("Animation set to: " + ANIMATION);
}
if (gAvieNum > -1) {
if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) {
StopAllAnims();
llStartAnimation(ANIMATION);
}
}
}
StopAllAnims() {
list anims = llGetAnimationList(gAvieKey);
integer n;
integer cnt = llGetListLength(anims);
for (n=0; n < cnt; n++)
llStopAnimation(llList2String(anims,n));
}
InitAvie()
{
SetAnim();
gAvieNum = -1;
key id = llAvatarOnSitTarget();
if (id != NULL_KEY) {
gAvieKey = id;
integer i;
integer cnt = llGetNumberOfPrims();
for (i=1; i<=cnt; i++) {
if (llGetLinkKey(i) == id) gAvieNum = i;
}
if (gAvieNum > -1)
if (SIT_TEXT_HIDEONSIT) llSetText("", SIT_TEXT_COLOR, SIT_TEXT_ALPHA);
if (HIDE_POSEBALL_ON_SIT) llSetAlpha(0.0,ALL_SIDES);
llRequestPermissions(id, PERMISSION_TRIGGER_ANIMATION);
} else {
if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) {
StopAllAnims();
if (SIT_TEXT == "*") llSetText(llGetObjectName() + "\n" + llGetObjectDesc() + "\n" + ANIMATION, <0,0,1>, 0.5);
else llSetText(SIT_TEXT, SIT_TEXT_COLOR, SIT_TEXT_ALPHA);
if (HIDE_POSEBALL_ON_SIT) llSetAlpha(1.0,ALL_SIDES);
}
}
}
default
{
state_entry()
{
InitUserVariables();
SetAnim();
llSetText(SIT_TEXT, SIT_TEXT_COLOR, SIT_TEXT_ALPHA);
llSitTarget(SIT_POSITION-<0,0,0.35443>,llEuler2Rot(SIT_ROTATION * DEG_TO_RAD));
llSetCameraEyeOffset(SIT_CAMERA_POSITION); //Looking from
llSetCameraAtOffset(SIT_CAMERA_FOCUS); //Looking at
InitAvie();
}
on_rez(integer prm)
{
llResetScript();
}
changed(integer change)
{
if (change & CHANGED_LINK) {
InitAvie();
}
if (change & CHANGED_INVENTORY) {
SetAnim();
}
}
run_time_permissions(integer perm)
{
if (perm & PERMISSION_TRIGGER_ANIMATION) {
StopAllAnims();
llStartAnimation(ANIMATION);
llSetLinkPrimitiveParams(gAvieNum, [
PRIM_POSITION, SIT_POSITION,
PRIM_ROTATION, llEuler2Rot(SIT_ROTATION * DEG_TO_RAD)/llGetLocalRot()]);
}
}
}
Positioner Script:
CODE
//This script was written by Katherine Taney, it is free to use, modify, give away, etc....
//Please give credit and stuffs, stealing is wrong and bad and stuffs....
integer CONTROLS;
integer gAvieNum = -1;
key gAvieKey;
vector gAviePos = <0,0,0>;
vector gAvieRot = <0,0,0>;
float gMoveAmount = 0.1;
integer gRotAmountIndex = 5;
list ROTATIONAMOUNTS = [
1.0,5.0,10.0,15.0,30.0,45.0,90.0
];
vector SIT_TARGET_OFFSET = <0,0,0.35443>;
integer MODE = 0;
integer MODE_POSITION = 0;
integer MODE_ROTATION = 1;
integer MOVEMENT = 0;
integer MOVEMENT_LOCAL = 0;
integer MOVEMENT_WORLD = 1;
integer MOVEMENT_AVIE = 2;
integer gListenHandle;
integer INITIALIZING = FALSE;
integer gCurrentMenuOffest = 0;
integer gListenChannel = -194288;
integer gLnkMsgNumReturn = -455;
integer gLnkMsgNumCall = -456;
list gCurrentButtonList = [];
string gCurrentTitle = "";
InitControls()
{
INITIALIZING = TRUE;
llListenRemove(gListenHandle);
gListenChannel = (integer)(llFrand(-1000000000.0) - 1000000000.0);
gListenHandle = llListen(gListenChannel, "", NULL_KEY, "");
key id = llAvatarOnSitTarget();
gAvieNum = -1;
if (id != NULL_KEY) {
gAvieKey = id;
integer i;
integer cnt = llGetNumberOfPrims();
for (i=1; i<=cnt; i++) {
if (llGetLinkKey(i) == id) gAvieNum = i;
}
if (gAvieNum > -1)
llRequestPermissions(llGetLinkKey(gAvieNum), PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA | PERMISSION_CONTROL_CAMERA);
} else {
if (llGetPermissions() & PERMISSION_CONTROL_CAMERA) {
llReleaseControls();
llClearCameraParams();
llReleaseCamera(gAvieKey);
}
}
}
SetCamera()
{
vector campos = llGetCameraPos();
rotation camrot = llGetCameraRot();
llSetCameraParams([
CAMERA_ACTIVE, 1, // 1 is active, 0 is inactive
CAMERA_FOCUS, campos + llRot2Fwd(camrot), // region-relative position
CAMERA_FOCUS_LAG, 0.0 , // (0 to 3) seconds
CAMERA_FOCUS_LOCKED, TRUE, // (TRUE or FALSE)
CAMERA_FOCUS_THRESHOLD, 0.0, // (0 to 4) meters
CAMERA_POSITION, campos, // region-relative position
CAMERA_POSITION_LAG, 0.0, // (0 to 3) seconds
CAMERA_POSITION_LOCKED, TRUE, // (TRUE or FALSE)
CAMERA_POSITION_THRESHOLD, 0.0 // (0 to 4) meters
]);
}
Mark()
{
llSay(-123456, "!MARK~" + (string)llGetRootPosition() + "~" + (string)llGetLocalPos() + "~" + (string)llGetRootRotation() + "~" + (string)llGetLocalRot() + "~" + (string)gAviePos + "~" + (string)gAvieRot);
}
list GetMenuList(list btnList)
{
//llOwnerSay(llList2CSV(btnList));
integer i;
list tmpMenuList = [];
integer listLen = llGetListLength(btnList);
integer buttoncount = 12;
if (gCurrentMenuOffest > 0) {
--buttoncount;
tmpMenuList = ["<-Back"];
}
if (listLen > buttoncount) --buttoncount;
integer stopPos = buttoncount;
if (listLen > buttoncount) {
stopPos = gCurrentMenuOffest + buttoncount;
}
if (stopPos > listLen) stopPos = listLen;
for (i=gCurrentMenuOffest;i<stopPos;i++) {
tmpMenuList += llList2String(btnList,i);
}
if (listLen > stopPos) tmpMenuList += ["Next->"];
return tmpMenuList;
}
HandleControl(integer held, integer change)
{
if (!INITIALIZING) {
//llOwnerSay((string)held + "~" + (string)change);
SetCamera();
vector mv;
float amt;
if (MODE == MODE_POSITION) amt = gMoveAmount;
else if (MODE == MODE_ROTATION) amt = llList2Float(ROTATIONAMOUNTS, gRotAmountIndex);
if (held & change & CONTROL_FWD) mv += <amt, 0.0, 0.0>;
if (held & change & CONTROL_BACK) mv += <-amt, 0.0, 0.0>;
if (held & change & CONTROL_UP) mv += <0.0, 0.0, amt>;
if (held & change & CONTROL_DOWN) mv += <0.0, 0.0, -amt>;
if (held & change & CONTROL_ROT_LEFT) mv += <0.0, -amt, 0.0>;
if (held & change & CONTROL_ROT_RIGHT) mv += <0.0, amt, 0.0>;
if (MOVEMENT == MOVEMENT_WORLD) mv = mv / llGetLocalRot();
else if (MOVEMENT == MOVEMENT_AVIE) mv = mv * llEuler2Rot(gAvieRot*DEG_TO_RAD);
if (mv != ZERO_VECTOR) {
if (MODE == MODE_POSITION) {
gAviePos += mv;
llSetLinkPrimitiveParams(gAvieNum, [PRIM_POSITION, gAviePos]);
}
else if (MODE == MODE_ROTATION) {
gAvieRot += mv;
llSetLinkPrimitiveParams(gAvieNum, [PRIM_ROTATION, llEuler2Rot(gAvieRot*DEG_TO_RAD)/llGetLocalRot()]);
}
Mark();
}
if (held & change & CONTROL_RIGHT) {
if (MODE == MODE_POSITION) {
gMoveAmount *= 10;
llOwnerSay("Move amount set to " + (string)gMoveAmount);
}
else if (MODE == MODE_ROTATION) {
gRotAmountIndex += 1;
if (gRotAmountIndex > llGetListLength(ROTATIONAMOUNTS)-1) gRotAmountIndex = 0;
llOwnerSay("Rotate amount set to " + llList2String(ROTATIONAMOUNTS, gRotAmountIndex));
}
}
if (held & change & CONTROL_LEFT) {
if (MODE == MODE_POSITION) {
gMoveAmount /= 10;
llOwnerSay("Move amount set to " + (string)gMoveAmount);
}
else if (MODE == MODE_ROTATION) {
gRotAmountIndex -= 1;
if (gRotAmountIndex < 0) gRotAmountIndex = llGetListLength(ROTATIONAMOUNTS)-1;
llOwnerSay("Rotate amount set to " + llList2String(ROTATIONAMOUNTS, gRotAmountIndex));
}
}
}
}
default
{
state_entry()
{
CONTROLS = CONTROL_FWD | CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_UP | CONTROL_DOWN | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT;
InitControls();
}
run_time_permissions(integer perm)
{
if (perm & PERMISSION_TAKE_CONTROLS) {
llTakeControls(CONTROLS, 1, 0);
llSetTimerEvent(1.2);
}
}
changed(integer change)
{
if (change & CHANGED_LINK) {
InitControls();
}
}
control(key id, integer held, integer change)
{
HandleControl(held, change);
}
timer()
{
llSetTimerEvent(0.0);
llSetLinkPrimitiveParams(gAvieNum, [PRIM_POSITION, gAviePos, PRIM_ROTATION, llEuler2Rot(gAvieRot*DEG_TO_RAD)/llGetLocalRot()]);
SetCamera();
llSay(-123456, "!CONTROL~" + (string)gAvieKey + "~" + (string)gListenChannel);
llSay(-123456, "!CONFIG~" + (string)MODE + "~" + (string)MOVEMENT + "~" + (string)gAvieKey);
Mark();
llOwnerSay("Avie positioner active");
INITIALIZING = FALSE;
}
touch_start(integer total_number)
{
list btnlist = ["ZERO"];
if (MODE == MODE_POSITION) btnlist += "Rotation";
else if (MODE == MODE_ROTATION) btnlist += "Position";
if (MOVEMENT == MOVEMENT_LOCAL) btnlist += "World";
else if (MOVEMENT == MOVEMENT_WORLD) btnlist += "Avatar";
else if (MOVEMENT == MOVEMENT_AVIE) btnlist += "Local";
btnlist += "Report";
string title =
"Avatar Postition: " + (string)gAviePos + "\n" +
"Avatar Rotation (DEG): " + (string)gAvieRot + "\n" +
"Pose Positioner Options:";
llMessageLinked(LINK_SET, -456, llDumpList2String([-455, title] + btnlist, "~"), llDetectedKey(0));
}
link_message(integer sender_num, integer num, string str, key id)
{
if (num == gLnkMsgNumCall) {
gCurrentMenuOffest = 0;
list tmp = llParseString2List(str, ["~"], []);
gLnkMsgNumReturn = (integer)llList2String(tmp, 0);
gCurrentTitle = llList2String(tmp, 1);
tmp = llListReplaceList(tmp, [], 0,1);
gCurrentButtonList = tmp;
llDialog(id, gCurrentTitle, GetMenuList(gCurrentButtonList), gListenChannel);
}
else if (num == -455) {
if (str == "Rotation") {
MODE = MODE_ROTATION;
llOwnerSay("Rotation mode selected");
}
else if (str == "Position") {
MODE = MODE_POSITION;
llOwnerSay("Position mode selected");
}
else if (str == "World") {
MOVEMENT = MOVEMENT_WORLD;
llOwnerSay("World movement selected");
}
else if (str == "Local") {
MOVEMENT = MOVEMENT_LOCAL;
llOwnerSay("Local movement selected");
}
else if (str == "Avatar") {
MOVEMENT = MOVEMENT_AVIE;
llOwnerSay("Avatar movement selected");
}
else if (str == "ZERO") {
gAviePos = ZERO_VECTOR;
gAvieRot = ZERO_VECTOR;
llSetLinkPrimitiveParams(gAvieNum, [PRIM_POSITION, gAviePos, PRIM_ROTATION, llEuler2Rot(gAvieRot*DEG_TO_RAD)/llGetLocalRot()]);
Mark();
llOwnerSay("Zeroed");
}
else if (str == "Increase") {
if (MODE == MODE_POSITION) {
gMoveAmount *= 10;
llOwnerSay("Move amount set to " + (string)gMoveAmount);
}
else if (MODE == MODE_ROTATION) {
gRotAmountIndex += 1;
if (gRotAmountIndex > llGetListLength(ROTATIONAMOUNTS)-1) gRotAmountIndex = 0;
llOwnerSay("Rotate amount set to " + llList2String(ROTATIONAMOUNTS, gRotAmountIndex));
}
}
else if (str == "Decrease") {
if (MODE == MODE_POSITION) {
gMoveAmount /= 10;
llOwnerSay("Move amount set to " + (string)gMoveAmount);
}
else if (MODE == MODE_ROTATION) {
gRotAmountIndex -= 1;
if (gRotAmountIndex < 0) gRotAmountIndex = llGetListLength(ROTATIONAMOUNTS)-1;
llOwnerSay("Rotate amount set to " + llList2String(ROTATIONAMOUNTS, gRotAmountIndex));
}
}
else if (llGetSubString(str, 0, 2) == "SET") {
if (llGetSubString(str, 3, 3) == "P") {
gMoveAmount = (float)llGetSubString(str, 4, -1);
llOwnerSay("Move amount set to " + (string)gMoveAmount);
}
else if (llGetSubString(str, 3, 3) == "R") {
gRotAmountIndex = llListFindList(ROTATIONAMOUNTS, [(float)llGetSubString(str, 4, -1)]);
if (gRotAmountIndex == -1) gRotAmountIndex = 5;
llOwnerSay("Rotate amount set to " + llList2String(ROTATIONAMOUNTS, gRotAmountIndex));
}
}
else if (str == "Report") {
llOwnerSay("\n" +
"SIT_POSITION = " + (string)gAviePos + ";\n" +
"SIT_ROTATION = " + (string)(llRot2Euler(llEuler2Rot(gAvieRot*DEG_TO_RAD))*RAD_TO_DEG) + ";"
);
}
else {
if (str == "X+") HandleControl(CONTROL_FWD, CONTROL_FWD);
else if (str == "X-") HandleControl(CONTROL_BACK, CONTROL_BACK);
else if (str == "Y+") HandleControl(CONTROL_ROT_RIGHT, CONTROL_ROT_RIGHT);
else if (str == "Y-") HandleControl(CONTROL_ROT_LEFT, CONTROL_ROT_LEFT);
else if (str == "Z+") HandleControl(CONTROL_UP, CONTROL_UP);
else if (str == "Z-") HandleControl(CONTROL_DOWN, CONTROL_DOWN);
else llOwnerSay("ERR: " + str);
}
llSay(-123456, "!CONFIG~" + (string)MODE + "~" + (string)MOVEMENT + "~" + (string)gAvieKey);
Mark();
}
}
listen(integer channel, string name, key id, string str)
{
if (str == "<-Back") {
gCurrentMenuOffest -= 11;
llDialog(id, gCurrentTitle, GetMenuList(gCurrentButtonList), gListenChannel);
} else if (str == "Next->") {
gCurrentMenuOffest += 11;
llDialog(id, gCurrentTitle, GetMenuList(gCurrentButtonList), gListenChannel);
} else {
llMessageLinked(LINK_SET, gLnkMsgNumReturn, llStringTrim(str, STRING_TRIM), id);
}
}
}
I've placed a box in my shop that includes both of these scripts, plus a HUD to control positioning, a marker that follows the avie to show local coordinates, an example with everything assembled and ready to use, and a zero pose. The box is for sale for L$0.