Need help with script to make me frown when i attach the object containing the script
|
Gattz Gilman
Banned from RealLife :/
Join date: 29 Feb 2004
Posts: 316
|
08-04-2004 17:01
IM in the works of making a Riddick avatar, and i find that you cant really get an avatar to look like its frowning with the provided sliders in the appearence. So i wanted to make an oscript that would make me play the "frown" anim over and over. I made a script, and all looks like it should work, but all i get is lots of particles flying around :/, not exactly what i was looking for. This is what i made so far: default { state_entry() { llRequestPermissions("", PERMISSION_TRIGGER_ANIMATION); llSetTimerEvent(0.1); }
timer() { llStartAnimation("frown"); llStopAnimation("frown"); } }
-------------------------- Gattz Gilman, SG Lair Co-Owner Sistiana
|
Ama Omega
Lost Wanderer
Join date: 11 Dec 2002
Posts: 1,770
|
08-04-2004 19:16
The basics: Change the state_entry() to a attach() event, change the timer to a run_time_permissions event.
Take a look at some other scripts that work when attached, especially if they take controls or animate the avatar. The above is really just the basics, you need to put in some checks and balances so things only happen when they should.
_____________________
-- 010000010110110101100001001000000100111101101101011001010110011101100001 --
|
Gattz Gilman
Banned from RealLife :/
Join date: 29 Feb 2004
Posts: 316
|
08-05-2004 14:14
kk, i tried that and..well.. no luck  . im sorry, but i guess i put my time in making clothes then scripting. here is what i did for the script. default { attach(key on) { if (on != NULL_KEY) { llListen(0,"",llGetOwner(),""); integer perm = llGetPermissions(); if (perm != (PERMISSION_TRIGGER_ANIMATION)) { llRequestPermissions(on, PERMISSION_TRIGGER_ANIMATION); } } }
run_time_permissions(integer perm) { if (perm) { llStartAnimation("frown"); llStopAnimation("frown"); } }
}
btw, thanx for your help 
|
Wednesday Grimm
Ex Libris
Join date: 9 Jan 2003
Posts: 934
|
08-05-2004 14:33
I think you're almost there, try this: default { attach(key on) { if (on != NULL_KEY) { integer perm = llGetPermissions(); if (!(perm & PERMISSION_TRIGGER_ANIMATION)) { llRequestPermissions(on, PERMISSION_TRIGGER_ANIMATION); } else { llSetTimerEvent(0.5); } } }
run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { llSetTimerEvent(0.5) } }
timer() { llStopAnimation("frown"); llStartAnimation("frown"); } }
_____________________
Sarcasm meter: 0 |-----------------------*-| 10 Rating: Awww Jeeze!
|
Gattz Gilman
Banned from RealLife :/
Join date: 29 Feb 2004
Posts: 316
|
08-08-2004 17:07
it wasnt working at first but that was cause i didnt have the right name for the anim, but for some reason it works for a little while, then stops, and i cant figure out why. default { attach(key on) { if (on != NULL_KEY) { integer perm = llGetPermissions(); if (!(perm & PERMISSION_TRIGGER_ANIMATION)) { llRequestPermissions(on, PERMISSION_TRIGGER_ANIMATION); } else { llSetTimerEvent(0.5); } } }
run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { llSetTimerEvent(0.5); } }
timer() { llStopAnimation("express_frown"); llStartAnimation("express_frown"); } }
|
Gwyneth Llewelyn
Winking Loudmouth
Join date: 31 Jul 2004
Posts: 1,336
|
08-09-2004 07:06
Hello, I read the above posts and it very much looks like something I need. I have several problems with scripts combining attach() events with getpermission() events and state changes. Basically I'm doing things like: get the object attached, check for permissions from the user, change state, now do something - play an animation, set a timer, listen for vocal commands, get an object from the inventory and give it to the user, etc. Quite basic stuff. After a while I got a structure very similar to what was posted here by Master Scripting Gurus Wednsday & Ama (thanks for your support guys, I keep reading and following your many examples and have learnt quite a lot with you!) and this worked well. For my avatar, that is. As soon as I give the object containing the script to someone else - either directly or thropugh an object, say, a vending machine - I completely lose control of my state changes! Theoretically I should be in the "finished" state (ie. unattached) when I give the object. But things get so weird afterwards that some users using my objects get the replies from the attach() even THE OTHER WAY ROUND, ie they get NULL_KEY when they attach things, and the avatar's key when deattaching! At least, by debugging with llWhisper and so, it surely looks like the state machine is "inverted" and giving out the wrong answers! Now THIS CAN'T BE RIGHT. I've tested several scripts with state changes and they all work well, both with my avatar and with people I give the objects to. I believe that my problem is with an incorrect usage of state_entry() and on_rez() events. From what I read on the Wiki (not always 100% in sync with LL's 2003 docs), state_entry() is called when the object ever gets created (but not rezzed yet). Question 1: when you give it to someone else, or make a copy of it, will default:  tate_entry() be called ever again? Ie. copies of the same object are really copies, or are they the same instance of the original objects? (this would look like the case, when I am in a "finished" state and give the object away or make a copy of it, it's still in the finished state. And there seems to be no way to reset the script from INSIDE the inventory - either the avatar's or a vending machine's - to it's initial state. Or is there a way? How? Also, the Wiki says that ALL states will call state_entry() every time the state is changed EXCEPT for default:  tate_entry(), which is only called ONCE (or when you call llResetScript()). Is that so? In that case, it doesn't make any sense to return to the default state again. I should have two extra states, attachment_worn and atttachment_notworn, and use the default state just for initialization. Is that correct? Finally, the on_rez() is called only when the object is dropped on the ground. Is that correct? It won't be called when the object is in an avatar's inventory and attached/worn? You ONLY use the attach event for that, right? I like the solution you propose above of checking the permissions and putting initialization code there. However, once again, the LSL Wiki warns that the new versions of SL may NOT ALWAYS ask for permissions. This seems to be true. Once an avatar gives permission to use my object, it will have permissions "for ever" and will never call the run_time_permissions() again. Or will the current state always call this event when it needs to do so, but with permissions correctly set?? (I haven't figured that out yet). This COULD be a way to make sure I get the object in the proper state, then... So this means that I have to find out which state I'm currently in, and reset the script to the state I want, because I cannot know beforehand what happens when the user gets a copy of my object. But this doesn't make any sense, the only way I can know the state is by expecting the object to call the correct events... Well basically what I need is a way to reset scripts before copying objects! (either into my inventory or from a vending machine's point of view) This probably means calling llResetScript() correctly without getting into an infinite loop. Because from my own experience, when MY avatar is using the object, it gets the state machine correctly reset, but just picking it up, resetting manually, and give it to someone else's avatar will change the state machine to a unpredictable state...
|
Catherine Omega
Geometry Ninja
Join date: 10 Jan 2003
Posts: 2,053
|
08-09-2004 09:48
The state_entry() event is triggered when entering a state. A script enters the default state when the script starts. So if you reset the it, or recompile it, or place the script into a new object, it will Remember that script memory states (not the same as the "states" we're talking about here) persist even if the object is taken into inventory or transferred. So if someone else is getting permissions problems, it's likely that your key is persisting after you transfer ownership. Putting llResetScript in your on_rez event will cause your script to reset every time it's rezzed, so assuming there's nothing else in on_rez, the first event to be triggered would be default{state_entry(). state_entry is NOT called when the script is unrezzed, as scripts do not run until they're placed in an object. Copying an object does not duplicate the memory state. The new copy behaves as a "fresh" version, starting with default{state_entry. From: someone Also, the Wiki says that ALL states will call state_entry() every time the state is changed EXCEPT for default:  tate_entry(), which is only called ONCE (or when you call llResetScript()). Is that so? Can you show me where the wiki says this? It's not so. state_entry() and state_exit() are called on every state change, EXCEPT when "changing" to the current state. (IE, if we're in state default, and we attempt to SWITCH to state default, then they won't trigger -- to get around that, just make another state that's only used to switch back to state default.) on_rez() is called when the object is rezzed in world. So either dropped on the ground or attached directly from inventory to the avatar. If an object is already in world when the script starts, on_rez() will NOT be called, nor will it be called when it is attached. attach() WILL be called if the object is already attached when the script starts. When rezzing an attachment from inventory, on_rez() will be called before attach(). Now, all that said, are you sure you need to bother using states? 
|
Gwyneth Llewelyn
Winking Loudmouth
Join date: 31 Jul 2004
Posts: 1,336
|
08-10-2004 08:26
Well thanks Catherine for your looong answer. It made me seriously think about my own scripts and a general approach to LSL in general.
So I trashed all my complicated code and started from scratch, using your guidelines. At first I was impressed: I could get the same results with less code! Due to the events the code is not so easy to read (that's the problem with event-driven programming anyway...) but it sure looks much simpler and cleaner.
After spending several hours getting through all my scripts and changing them, rebuilding objects, etc. and adding here and there extra functionality, I was very happy with the results. Same functionality, much less code, mush simpler and with less "annoying bugs".
But I found out the bug with my scripts. The thing is, when I give the objects away, they seem always to be in the "active" state (ie. worn/attached) and they should be in the default state instead. I tried to figure out why that happens all the time, even when I reset the script and give it away, or if the object is taken from inside a vendor machine.
So what I do now is check on_rez() on the "active" states and jump back to default! Works well enough on some of the scripts! I'm going to change it on ALL scripts to see if they FINALLY start working on other people, too!
Thanks again for all your time in explaining the few subtle things I had missed.
Love,
Gwyn
PS. Yes you're right with the LSL Wiki, it's correct. I had interpreted it wrongly. And your explanation is so good it deserves to be added as an extra comment on the Wiki...
PPS. Here I go back again to my scripting sessions...
|
Sabbie DeGroot
Dutchy
Join date: 26 Jul 2004
Posts: 59
|
08-17-2004 04:01
Hi,
I tryed this script and it works, thanks for that, one thing I still don't understand though. If attach() is triggered when you attach the object with the script, why does it animate your ava when you just rez it in the world?
Thanks,
|
Gwyneth Llewelyn
Winking Loudmouth
Join date: 31 Jul 2004
Posts: 1,336
|
08-17-2004 08:33
Now that's a very good question! It seems that whenever you give an object away that you have already worn, rezzing it by someone else will call attach() (sometimes with an UNEXPECTED key... like 0!) An object which is going to get attached will be probably always tried out by the owner at least once! This is valid if you put the object inside a vending machine, too. It will inherit the state it had when it was in YOUR inventory. I usually reset the scripts manually just when I drop them inside other objects (vending machines, etc.). However, if you give the object away to someone else, this is not possible to do. You *could* rez it, reset the script, and ask the next person to pick it up - *if* you got permissions to rez objects in that particular region! So far this is one of my biggest problems, getting scripts to properly initialize themselves. Yes, I know there are basically two or three ways to do it: - call llResetObject(); - provide an init() function which will initialize your object in some way, and call it from every state_entry or on_rez events on all your states. Depending on the type of object and the persistent data it carries (counters, etc.) there are different approaches to the problem. I'm always impressed with other people's objects which are stupidly simple and always work correctly when I get a copy of them. 
|
Sabbie DeGroot
Dutchy
Join date: 26 Jul 2004
Posts: 59
|
08-17-2004 09:26
Hmmm, so that's the problem.. Well, I'm a total noob to SL and LSL, so I probally make no sence, but.. Wouldn't this work then: on_rez() { llResetScript(); }
??
|
Gwyneth Llewelyn
Winking Loudmouth
Join date: 31 Jul 2004
Posts: 1,336
|
08-17-2004 09:43
That depends, Sabbie. You can do that if you really don't need to keep any state at all inside your object! And it will work well. This means that if the object is in some kind of weird state, when rezzed, it will start correctly in the "first" (default) state again.
On the other hand, if you need to mantain state (say, a counter or so) between on_rez things are not so easy, specially if you can't figure out what state your object is when you give it away!
Let me give you an example. You design a box of candies. It gives out 5 candies then it disappears. Avatars can give half-full candy boxes to other avatars, and I expect the count to stay correct.
This means that if I take 3 candies out and give it to someone else (on_rez() would be called that way!) I expect the box to have 2 candies left. Put into other words, there is a global variable for the counter which is only set ONCE for that object's lifetime. This can't change when objects change owners or state.
So I can't always rely on llResetScript() for that.
On the other hand, it works well for all objects that don't need to keep reference counts or so, just have an attached/unattached state, or a state responding to vocal commands, or responding to "touch". In those cases i do exactly what you suggest: call llResetScript() on all on_rez instances (for all states).
|
Sabbie DeGroot
Dutchy
Join date: 26 Jul 2004
Posts: 59
|
08-18-2004 05:20
Allright, I checked it ingame and Rickard Roentgen and Zite Virgo helped me to get this (working!) solution: default { on_rez(integer start_param) { llSetTimerEvent(0.0); } attach(key on) { llSetTimerEvent(0.0); if (on != NULL_KEY) { integer perm = llGetPermissions(); if (!(perm & PERMISSION_TRIGGER_ANIMATION)) { llRequestPermissions(on, PERMISSION_TRIGGER_ANIMATION); } else { llSetTimerEvent(0.5); } } }
run_time_permissions(integer perm) { if (perm & PERMISSION_TRIGGER_ANIMATION) { llSetTimerEvent(0.5); } }
timer() { llStopAnimation("Animation-here"); llStartAnimation("Animation-here"); } }
|
Catherine Omega
Geometry Ninja
Join date: 10 Jan 2003
Posts: 2,053
|
08-18-2004 10:48
From: someone Originally posted by Gwyneth Llewelyn That depends, Sabbie. You can do that if you really don't need to keep any state at all inside your object! And it will work well. This means that if the object is in some kind of weird state, when rezzed, it will start correctly in the "first" (default) state again.
On the other hand, if you need to mantain state (say, a counter or so) between on_rez things are not so easy, specially if you can't figure out what state your object is when you give it away! Almost. To be more precise, you can do that if you don't need to worry about state within that script. Say you have two scripts in an object: one that does something relatively simple like animating your avatar, and one that relies heavily upon state. You can run them in different scripts within a single object. Rezzing the object will reset the unimportant script, but leave the complex one alone.
|