i've made a little owl that will follow me and i want it to face me as i move around it should follow and face me. unfortunately it always lays on it's back in the air with it's feet always pointed at me. what am i doing wrong? i suppose you could put this script in a cube with colored sides if you want to see what i mean.
key followUser;
rotation gRotObjectRot;
vector gVecObjectPos;
rotation NormRot(rotation Q)
{
float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);
return
<Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>;
}
fnLookAtMe(vector gVecObjectPos,rotation gRotObjectRot)
{
vector ownPosition = llGetPos();
rotation ownRotation = llGetRot();
vector detectedPosition = gVecObjectPos;
rotation detectedRotation = gRotObjectRot;
llSetKeyframedMotion(
[(detectedPosition - ownPosition) + <0.0, 1.0, 0.0>*detectedRotation,
NormRot(detectedRotation/ownRotation), 0.12],
[]);
}
key getAgentByName(string firstName)
{
firstName = llToLower(firstName);
list ag = osGetAvatarList();
integer howmany = llGetListLength(ag);
integer i;
for (i =0; i < howmany; i+=3)
{
string name = llList2String(ag, i+2);
integer sep = llSubStringIndex(name, " ");
if (llToLower(llGetSubString(name, 0,sep-1)) == firstName)
{
return llList2Key(ag, i);
}
}
return NULL_KEY;
}
default
{
on_rez(integer n)
{
llResetScript();
}
state_entry()
{
llListen(0, "", "", "");
llSetLinkPrimitiveParams(2, [PRIM_OMEGA, <0, 0,0> , 4., 1.]);
}
listen(integer chan, string w, key id, string msg)
{
list l = llParseString2List(msg, [" "], []);
if (llList2String(l , 0) == llGetObjectName())
{
string c = llList2String(l , 1);
if (c == "come")
{
list userData=llGetObjectDetails((key)id, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
vector v = llList2Vector(userData, 1);
llSetRegionPos( v+<0,0,2>);
}
else if (c == "pickup")
{
string name= llList2String(l , 2);
key u;
if (name =="me" || name == "") u = id;
else u = getAgentByName(name);
osForceOtherSit(u);
}
else if (c == "fetch")
{
string name= llList2String(l , 2);
key u;
if (name =="me" || name == "")
{
u = id;
}
else
{
u = getAgentByName(name);
}
list userData=llGetObjectDetails((key)u, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
list mydata=llGetObjectDetails((key)id, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
followUser =NULL_KEY;
llSetTimerEvent(0);
if (llGetListLength(userData)>0 && llGetListLength(mydata)>0)
{
vector v = llList2Vector(userData,1);
vector mypos = llList2Vector(mydata,1);
llSetKeyframedMotion( [], []);
llSleep(.5);
llSetRegionPos(v+ <0,0,3>);
llSleep(.5);
osForceOtherSit(u);
llSleep(.3);
list kf;
kf += <0,0,10>;
kf += ZERO_ROTATION;
kf += 3;
kf += mypos - v;
kf += ZERO_ROTATION;
float t = llVecDist(mypos, v)/10;
if (t > 20) t = 20;
kf += t;
kf += <0,0,-10>;
kf += ZERO_ROTATION;
kf += 3;
llSetKeyframedMotion( kf, [KFM_DATA, KFM_TRANSLATION|KFM_ROTATION, KFM_MODE, KFM_FORWARD]);
}
else llSay(0, name + " Not found");
}
else if (c == "follow")
{
string name= llList2String(l , 2);
key u;
if (name =="me" || name == "") u = id;
else u = getAgentByName(name);
followUser = u;
if (followUser != NULL_KEY)
{
llSetTimerEvent(1.);
llStopSound();
}
}
else if (c == "drop")
{
integer i;
for (i=1; i <= llGetNumberOfPrims(); i++)
llUnSit(llAvatarOnLinkSitTarget(i));
}
else if (c == "stop")
{
llSetKeyframedMotion( [], []);
integer i;
for (i=1; i <= llGetNumberOfPrims(); i++)
llUnSit(llAvatarOnLinkSitTarget(i));
followUser =NULL_KEY;
llStopSound();
llSetLinkPrimitiveParams(2, [PRIM_OMEGA, <0, 0,0> , 4., 1.]);
}
else if (c == "help")
{
llSay(0, "Usage: "+llGetObjectName()+" come, follow <me|firstname>, fetch <name>, pickup <name>, drop, stop");
}
}
}
timer()
{
if (followUser!= NULL_KEY)
{
list userData=llGetObjectDetails((key)followUser, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
gVecObjectPos = llList2Vector(userData,1);
gRotObjectRot = llList2Rot(userData,2);
if (llGetListLength(userData)==0)
{
followUser = NULL_KEY;
llSetTimerEvent(0);
llSetLinkPrimitiveParams(2, [PRIM_OMEGA, <0, 0,0> , 4., 1.]);
}
else
{
llSetKeyframedMotion( [], []);
llSleep(.2);
list kf;
vector mypos = llGetPos();
vector size = llGetAgentSize(followUser);
llSetLinkPrimitiveParamsFast(3, [PRIM_OMEGA, <0, 0,0> , 1., 1.]);
vector v = llList2Vector(userData, 1)+<0.3, -1.5, -size.z/2+0.4> * llList2Rot(userData,2);
float t = llVecDist(mypos, v)/3;
if (t > 1.)
{
if (t > 10) t = 10;
vector vn = llVecNorm(v - mypos );
vn.z=0;
kf += v- mypos;
kf += ZERO_ROTATION;
kf += t;
rotation r2 = llRotBetween(<1,0,0>,vn);
llSetKeyframedMotion( kf, [KFM_DATA, KFM_TRANSLATION|KFM_ROTATION, KFM_MODE, KFM_FORWARD]);
llSetLinkPrimitiveParamsFast(3, [PRIM_OMEGA, <0,1,0>*(r2/llGetRot()) , 4., 1.]);
llSetLinkPrimitiveParamsFast(2, [PRIM_ROT_LOCAL, (llEuler2Rot(<1,0,0>*PI/2)*r2)/llGetRot() ]);
llSetTimerEvent(t);
fnLookAtMe(gVecObjectPos,gRotObjectRot);
}
if (llFrand(1)<.05) llTriggerSound("owl"+(integer)llFrand(4), 1.0);
}
}
}
touch_start(integer n)
{
llSay(0, "Usage: "+llGetObjectName()+" come, follow <me|firstname>, fetch <name>, pickup <name>, drop, stop");
}
}