Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Sit target system by Lex Neva. Please distribute willy-nilly.
- // learjeff innis: allow to leave script in furniture.
- // Note that shift-drag to copy will lose the sit target.
- // v2d: anim menu
- // v2e: shift-lef/right to switch anims
- // v2f: left/right to rotate (normal furniture mode only), and only if "Rotat" is in description
- // v2g: compensate for LSL bug? key sent to "control" is not always av on sit target!
- // v2h: comments, optimize stopping of default sits
- // v2i: ?
- // v2i1: fix rotation after getting up
- // v3: menu! Make it so finished furniture doesn't show a clickable cursor
- string HelperName = "Sit Target Helper 3";
- list Anims; // names of anims in object's inventory
- integer AnimNum; // index of current anim
- string LastAnim; // anim last sitter used
- key LastAv; // av who sat, just a guard
- rotation OrigRotation; // rotation to return seat to, when av stands
- integer Rotating; // whether rotating seat
- integer MenuChan;
- list Buttons = [
- "SET"
- , "DONE"
- ];
- // Return a channel number that's based on the prim's key -- unique per object
- integer channel() {
- return (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1));
- }
- do_menu(key id) {
- llDialog(id,
- "Choose SET to set the sit target. Then test."
- + "\nChoose DONE when you're happy."
- + "\nTo change the target later, reset the script."
- + "\n(e.g., select, and Tools -> Reset scripts in selection)",
- Buttons,
- MenuChan);
- }
- do_sensor() {
- // Find the helper
- llSensor(HelperName, NULL_KEY, ACTIVE|PASSIVE, 20, PI);
- llSay(0, "Searching for '" + HelperName + "'");
- }
- // Collect the set of anims in this prim
- get_anims()
- {
- integer ix;
- string anim;
- llUnSit(llAvatarOnSitTarget());
- Anims = [];
- for (ix = 0; TRUE; ix++) {
- anim = llGetInventoryName(INVENTORY_ANIMATION, ix);
- if (anim == "") {
- llWhisper(0, (string)llGetListLength(Anims) + " animations");
- return;
- }
- Anims += [anim];
- }
- }
- // Start the animation given by ordinal number
- integer start_anim(integer ix) {
- integer numAnims = llGetListLength(Anims);
- key id = llAvatarOnSitTarget();
- list anims = llGetAnimationList(id);
- integer jx;
- for (; jx < llGetListLength(anims); ++jx) {
- llStopAnimation(llList2String(anims, jx));
- }
- if (numAnims > 0) {
- string anim = llList2String(Anims, ix);
- llStartAnimation(anim);
- // If this is the first we've seen of this av, stop default sits
- if (LastAv == NULL_KEY) {
- llStopAnimation("sit");
- llStopAnimation("sit_generic");
- llStopAnimation("sit_female");
- }
- LastAnim = anim;
- LastAv = id;
- }
- return (numAnims > 1);
- }
- // Start the next anim in inventory
- next_anim()
- {
- AnimNum++;
- if (AnimNum >= llGetListLength(Anims)) {
- AnimNum = 0;
- }
- start_anim(AnimNum);
- }
- // Start the previous anim in inventory
- prev_anim()
- {
- AnimNum--;
- if (AnimNum < 0) {
- AnimNum = llGetListLength(Anims) - 1;
- }
- start_anim(AnimNum);
- }
- // Rotate the stool by the given angle
- rotate(float amt)
- {
- rotation rot = llGetRot();
- rotation r = llEuler2Rot(<0,0,amt * DEG_TO_RAD>);
- llSetRot(rot * r);
- }
- // React to an arrow or shift-arrow key
- handle_control(integer level, integer change) {
- key id = llAvatarOnSitTarget();
- if (level & CONTROL_RIGHT) {
- next_anim();
- llInstantMessage(id, LastAnim);
- } else if (level & CONTROL_LEFT) {
- prev_anim();
- llInstantMessage(id, LastAnim);
- } else if (level & CONTROL_ROT_LEFT) {
- rotate(-15.0);
- } else if (level & CONTROL_ROT_RIGHT) {
- rotate(15.0);
- }
- }
- // Calculate the sit target, compensating for the known bug
- // Big thanks to Lex Neva for this!
- calc_sit_target()
- {
- vector helper_pos = llDetectedPos(0);
- rotation helper_rot = llDetectedRot(0);
- vector my_pos = llGetPos();
- rotation my_rot = llGetRot();
- // calculate where the avatar actually is
- vector avatar_pos = helper_pos + <0,0,1> * helper_rot; // due to helper's sit target
- avatar_pos = avatar_pos - <0,0,0.186> + <0,0,0.4> * helper_rot; // correct for a bug in llSitTarget(), for helper sit target
- vector target_pos = (avatar_pos - my_pos) / my_rot;
- target_pos = target_pos + <0,0,0.186>/my_rot - <0,0,0.4>; // correct for the bug again, this time in my sit target
- rotation target_rot = helper_rot / my_rot;
- llSitTarget(target_pos, target_rot);
- llSay(0, "llSitTarget(" + (string)target_pos + ", " + (string)target_rot + ");");
- }
- upgrade() {
- string me = llGetScriptName();
- string name = "Sit Target Setter";
- integer n = llGetInventoryNumber(INVENTORY_SCRIPT);
- while (n-- > 0) {
- string item = llGetInventoryName(INVENTORY_SCRIPT, n);
- if (item != me && 0 == llSubStringIndex(item, name)) {
- llOwnerSay("removing old script: " + item);
- llRemoveInventory(item);
- }
- }
- }
- default
- {
- state_entry() {
- upgrade();
- state s_setting;
- }
- }
- // Sit-target setting mode
- // On click, show menu. On "SHOW", set the sit target. On "DONE", go to furniture mode.
- // Might be a good idea to disallow to simplify and avoid user mistakes.
- state s_setting
- {
- state_entry() {
- llSay(0, "Put desired sit animations in this prim "
- + "and in the Sit Target Helper.");
- llSay(0, "Sit on Sit Target Helper, move the helper to desired position, "
- + "and then click this prim to get menu");
- get_anims();
- MenuChan = channel();
- llListen(MenuChan, "", NULL_KEY, "");
- }
- on_rez(integer arg) {
- state default; // do this to reset chan, to avoid object crosstalk
- }
- touch_end(integer total_number) {
- do_menu(llDetectedKey(0));
- }
- listen(integer chan, string name, key id, string msg) {
- if (msg == "SET") {
- do_sensor();
- return;
- }
- if (msg == "DONE") {
- state s_normal;
- }
- }
- // no helper around, do nothing
- no_sensor() {
- llSay(0, "Can't find " + HelperName + ".");
- }
- // Found the helper: set sit target and go to furniture mode
- sensor(integer num) {
- if (num > 1) {
- llSay(0, "Multiple Sit Target Helpers found. Using closest one.");
- } else {
- llSay(0, "Setting sit target.");
- }
- calc_sit_target();
- }
- changed(integer change)
- {
- if (change & CHANGED_INVENTORY) {
- get_anims();
- return;
- }
- if (llAvatarOnSitTarget() == NULL_KEY)
- {
- LastAv = NULL_KEY; // nobody's sitting now
- }
- else
- {
- if (llAvatarOnSitTarget()!= llGetOwner())
- {
- llUnSit(llAvatarOnSitTarget() );
- return;
- }
- llRequestPermissions(llAvatarOnSitTarget() ,
- PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION);
- }
- }
- run_time_permissions(integer perm) {
- // allow shift-arrow for selecting pose, but not rotation in this state.
- llTakeControls(CONTROL_RIGHT | CONTROL_LEFT, TRUE, FALSE);
- if (start_anim(AnimNum)) {
- llInstantMessage(llAvatarOnSitTarget(),
- "shift-left/right to change animation");
- }
- }
- // Handle arrow keys
- control(key id, integer level, integer change) {
- handle_control(level, change);
- }
- state_exit() {
- llSetTimerEvent(0.0);
- llSay(0, "Converting to normal furniture mode");
- integer linknum = llGetLinkNumber();
- string text = "To put me back in sit-target programming mode, reset the '"
- + llGetScriptName() + "' script in ";
- if (linknum > 1) {
- text += "prim " + (string) linknum + " (" + llGetObjectName() + ")";
- } else {
- text += "this object";
- }
- llSay(0, text);
- }
- }
- state s_renormal {
- state_entry() {
- state s_normal;
- }
- }
- // Normal 'sit' mode: now we're just furniture.
- state s_normal
- {
- state_entry() {
- OrigRotation = llGetRot();
- }
- changed(integer change) {
- if (change & CHANGED_INVENTORY) {
- get_anims();
- return;
- }
- if (llAvatarOnSitTarget() == NULL_KEY) {
- LastAv = NULL_KEY; // nobody's sitting now
- if (Rotating) {
- llSetRot(OrigRotation); // restore original rotation
- }
- } else {
- OrigRotation = llGetRot(); // save current seat rotation
- llRequestPermissions(llAvatarOnSitTarget(),
- PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION);
- }
- }
- run_time_permissions(integer perm) {
- integer controls;
- // Grab shift-arrow keys for changing anims.
- // If "rotat" is anywhere in the description,
- // support rotation (i.e., also grab arrow keys).
- if (llSubStringIndex(llToUpper(llGetObjectDesc()), "ROTAT") == -1) {
- Rotating = FALSE;
- // anim changing only
- controls = CONTROL_RIGHT | CONTROL_LEFT;
- } else {
- Rotating = TRUE;
- // rotation support too
- controls = CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT;
- }
- llTakeControls(controls, TRUE, FALSE);
- if (start_anim(AnimNum)) {
- llInstantMessage(llAvatarOnSitTarget(),
- "shift-left/right to change animation");
- }
- }
- control(key id, integer level, integer change) {
- handle_control(level, change);
- }
- state_exit() {
- if (Rotating) {
- llSetRot(OrigRotation);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement