llSetKeyframedMotion is doing the trick. It's kinda tricky to deal with, but worth the effort. I'm sure my new script could be simpler, but here's the new Linked Driveshaft Rotation:Kayaker Magic wrote:Try using llSetKeyframedMotion to make your object rotate. You can call it once a second if you need to change the rotation often and let it run between timer events. This uses less server resources than calling llSetLinkPrimitiveParameters 32 times a second.
Code: Select all
string obj_name = "Anchor Driveshaft";
integer listen_chan = -42432;
float update_time = 30.0/45.0;
float cycle_time = -24.0;
float range = 8.0;
float x_rotation = 0.0;
float y_rotation = 0.0;
float z_rotation = -60.0;
float offset = 0.0;
vector base_pos = <0,0,0>;
rotation base_rot = <0,0,0,0>;
integer started = 0;
integer listen_handle;
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>;
}
default
{
state_entry()
{
list params = llGetLinkPrimitiveParams( LINK_THIS, [PRIM_ROTATION]);
base_rot = llList2Rot( params, 0 );
listen_handle = llListen( listen_chan, obj_name, "", "" );
llSetTimerEvent(update_time);
}
listen( integer channel, string name, key id, string message )
{
list values = llParseString2List( message, [" "], [] );
if ((llList2String(values,0) == "position") && (llList2String(values,4) == "rotation"))
{
llSetKeyframedMotion( [], [KFM_COMMAND, KFM_CMD_STOP] );
started = 0;
base_pos = < llList2Float(values,1),
llList2Float(values,2),
llList2Float(values,3) >;
vector new_rot = < llList2Float(values,5),
llList2Float(values,6),
llList2Float(values,7) >;
base_rot = llEuler2Rot(new_rot * DEG_TO_RAD);
}
}
timer()
{
float newTheta = (llGetTimeOfDay() + update_time) * 360.0 / cycle_time;
float x = x_rotation;
float y = y_rotation;
float z = z_rotation + newTheta;
rotation newRotation = llEuler2Rot(<x, y, z> * DEG_TO_RAD);
newRotation = newRotation * base_rot;
list params = llGetLinkPrimitiveParams( LINK_THIS, [PRIM_POSITION, PRIM_ROTATION]);
vector current_pos = llList2Vector( params, 0 );
rotation current_rot = llList2Rot( params, 1 );
vector move_to = <0.0, 0.0, 0.0>;
if (base_pos != ZERO_VECTOR)
{
move_to = base_pos - current_pos;
}
list KFMcommand = [];
if (!started) {
KFMcommand = [KFM_COMMAND, KFM_CMD_PLAY];
started = 1;
}
llSetKeyframedMotion( [ move_to, NormRot(newRotation / current_rot), update_time], KFMcommand );
}
}