Estelle Pienaar Posted February 18, 2015 Share Posted February 18, 2015 I am still very new to the concept of rotations in SL and LSLA few months ago I created a HUD for point-and-click adventure games in SL.I have also added a child mesh prim with one visible face.This is the principle how I build it: The child mesh prim for the storry telling textures is visible until I reset the script, then this prim with the texture is rotated by 90 degrees to an invisible face.The player takes the HUD from a vendor. When the player attaches the HUD it is still rotated to a side which is invisible. At a certain link-message command, the mesh prim rotates 90 degrees to its visible face and a texture can show a texture which tells part of the story. Here is a picture when the face with the texture is visible for the player:It wall works great, but here comes my problem: I need to reset the scripts quite often while I develop a game. If I do not rez the prim on the ground and edit the child prim so that the visible face is pointing towards the front, the function breaks when I reset the script. I have improvised with a channel listening for a comand ("turn-front") so that I do not have to rez the HUD all the time. But it is still tiring after the 100th reset. It would be so great if I could change this script, so that it works, even if the visible face is turned by 90 degrees to the side at the beginning. What do I need to change in my script? integer timerState; integer channel01; //Variables for Rotation of Story screen///////// integer forwardSwing = 90; rotation showRot; rotation hideRot; default { state_entry() { channel01 = llListen(5, "", llGetOwner(), ""); showRot = llGetLocalRot(); hideRot = llEuler2Rot( <0.0, 0.0, forwardSwing> * DEG_TO_RAD ); llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]); } link_message(integer source, integer num, string str, key id) { if (str =="STORY_1") { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]); timerState = 1; llSetTimerEvent(10.0); } } timer() { if (timerState == 1) { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]); llSetTimerEvent(0.0); //switch off timer } } listen(integer channel, string name, key id, string message) { if (message == "turn-front") llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]); else if (message == "turn-side") llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,hideRot]); } } Link to comment Share on other sites More sharing options...
Rolig Loon Posted February 18, 2015 Share Posted February 18, 2015 Have you tried using an attach event to trigger rotation to the default orientation? attach (key id){ if (id) { llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL,showRot]); }} All you have to do then is detach and reattach the HUD after you've done your editing. Link to comment Share on other sites More sharing options...
Xiija Posted February 19, 2015 Share Posted February 19, 2015 i use this for my HUD and it seems to work ok? rotate 90 forward...... llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTATION,llGetLocalRot() * llEuler2Rot(<0,0,90>*DEG_TO_RAD)]); rotate negative 90 back to position ...... llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROTATION,llGetLocalRot() * llEuler2Rot(<0,0,-90>*DEG_TO_RAD)]); Link to comment Share on other sites More sharing options...
Ron Khondji Posted February 19, 2015 Share Posted February 19, 2015 I would do something like: show: llSetLinkPrimitiveParams(child_link_num, [PRIM_ROT_LOCAL, llEuler2Rot(<.0, .0, .0> * DEG_TO_RAD)]); hide: llSetLinkPrimitiveParams(child_link_num, [PRIM_ROT_LOCAL, llEuler2Rot(<.0, .0, 90.0> * DEG_TO_RAD)]); This way there's no need to get the local rotation in state_entry Which also means that it doesn't matter wich way the child is rotated when you reset the script. Link to comment Share on other sites More sharing options...
Innula Zenovka Posted February 19, 2015 Share Posted February 19, 2015 The first question to ask when having difficulty rotating HUDs properly is, "What is the orientation of the HUD's root prim"? To work successfully, and to avoid tears of rage and frustration on your part, the root prim of the HUD has to be rotated to ZERO_ROTATION. That means, in practice, that the face that's visible by default to the user is face 4, the lesser x axis, It's the face that has the red arrow running into it when first you rez the prim, or when you examine the prim in Local Ruler mode. Check that, please. Unless that's right, the HUD won't work properly when you start rotating things. Link to comment Share on other sites More sharing options...
Estelle Pienaar Posted February 19, 2015 Share Posted February 19, 2015 Thanks to everyone for all your answers so far. I don't have the time to check the proposed solutions tonight, I will do that at the latest in the week-end. @ Innula: The HUD itself is zero rotation at the start. Also the child prim is zero rotation. BUT: Since the visible face of the child prim is rotated by 90 degrees counterclock-wise at the 1st state_entry event and it will most probably be out of sight, it is not anymore at the zero rotation when the scripts for the whole HUD are reset. Your remark might explain why the child prim is NOT rotated by another 90 degrees counterclock-wise after the 2nd state_entry event. I was wondering about that. And your remark might also explain why I was NOT getting the following to work: Start with the child prim 90 degrees rotated counter-clock wise. At state_entry make it rotate to zero rotaion thus show the visible face. Link to comment Share on other sites More sharing options...
Innula Zenovka Posted February 19, 2015 Share Posted February 19, 2015 I don' t know if this will solve your problem but, when I am making a HUD, I always have state_entry, and the attach event if appropriate, reset all the prims to their default positions, colour, visibility and so on. Doing that saves a lot of confusion in the long run. Link to comment Share on other sites More sharing options...
irihapeti Posted February 20, 2015 Share Posted February 20, 2015 is a wider design question to this as well which can be considered how to preserve current state when a script is restarted? + one way is to periodically save the state (a mapping) to linkset object description fields. On restart (state_entry) read from map and restore the last saved state to reduce the description field space requirement when is lots of state info, then can use a translation table in the script. A codemap can be quite useful this in game design. for debugging purposes like you wanting also for users who have reached a state (a game level say) and might need to reset the script on bork, and after doing this can still carry on in the game where they were last at same also if they detach. Save state so they can carry on when next attach + other thing to consider when doing this is having the ability to reset hot or cold hot meaning restore current state. cold meaning complete reset to default state can use either a chat command, or a dialog to set the signal (saved to the map) which is acted on in state_entry when the script restarts Link to comment Share on other sites More sharing options...
Estelle Pienaar Posted February 20, 2015 Share Posted February 20, 2015 The visible face cannot be in sight after state_entry or attach because it blocks the whole view (see picture). But I think I got the solution now, thanks to your remarks. I need to create a new mesh prim which has another unique face visible. Then face 4 will be invisible and can show to the front after the state_entry entry event. Link to comment Share on other sites More sharing options...
Estelle Pienaar Posted February 20, 2015 Share Posted February 20, 2015 I am using global variables instead of states for players to progress in the game. But the problem remains the same of course: after the reset of the script everything is reset to zero. I can only think of how backing-up to a database or writing/reading of a notecard works. How does mapping to the object description fields work? That sounds like a very interesting technique. Which LSL commands do I use for that? Link to comment Share on other sites More sharing options...
irihapeti Posted February 20, 2015 Share Posted February 20, 2015 read/write to the object description field with llSetObjectDesc and llGetObjectDesc simple codemap example: // code = "000"// 1st position: reset signal: 0 = cold reset. 1 = hot reset// 2nd position: orientation: indice of orient_map: range 0..3// 3rd position: color: indice of color_map: range 0..2integer RESET_HOT = 1; // name as constant for clarity // first element of list maps is the default statelist orient_map = [<0,0,0>,<0,0,90>,<0,0,180>,<0,0,270>];list color_map = [<1,0,0>, <0,1,0>, <0,0,1>];integer orient_idx;integer color_idx;codemapLoad(){ string code = llGetObjectDesc(); integer reset_signal = (integer)llGetSubString(code, 0, 0); if (reset_signal == RESET_HOT) { orient_idx = (integer)llGetSubString(code, 1, 1); color_idx = (integer)llGetSubString(code, 2, 2); } // when a indice > 9 then adjust getsubstring to accomodate // when code = "" then each will be 0: the default}codemapSave(integer reset_signal){ string code = (string)reset_signal + (string)orient_idx + (string)color_idx; llSetObjectDesc(code);}default{ state_entry() { codemapLoad(); llSetRot(llEuler2Rot(DEG_TO_RAD * llList2Vector(orient_map, orient_idx))); llSetColor(llList2Vector(color_map, color_idx), 4); } touch_start(integer num_detected) { if ((++orient_idx) == llGetListLength(orient_map)) orient_idx = 0; if ((++color_idx) == llGetListLength(color_map)) color_idx = 0; codemapSave(RESET_HOT); llResetScript(); }} + once get a feel for how codemaps work then can look into extending it further. Down the path you already thinking of. Where have a codemap database script (subsystem) seperate from your main game loop script. Communicating using link messages the subsytem doing the writing/reading locally to multiple description fields in the linkset if/when the extra storage space is needed. Game loop code treating the subsystem as it would any database database containing game values (levels, points, etc) as well as object properties as your game evolves then can go further. Extending the database subsytem to also read/write some data to a external website. Maybe a leaderboard for your players, etc + i tend to load/save indices as much as possible rather than read/write actual values to codemaps. Is easier to change the values in the lists when adding new capabilities as your game evolves over versions and you dont have to fiddle with formatting datatypes in the code string. Just have to add new indice fields to the end Link to comment Share on other sites More sharing options...
Estelle Pienaar Posted February 20, 2015 Share Posted February 20, 2015 Thank you very much! This is a very good trick to avoid php-database hassle. I will look into it. Link to comment Share on other sites More sharing options...
Innula Zenovka Posted February 20, 2015 Share Posted February 20, 2015 I would suggest you also keep an eye on developments with the new experience tools, currently being tested in particular regions. Among other things, they enable scripts to store values on LL's servers and to retrieve and update them in the dataserver event. Once experience tools are widely available, I think that's going to make a big difference to how some HUDs are made. 1 Link to comment Share on other sites More sharing options...
Xiija Posted February 20, 2015 Share Posted February 20, 2015 other options besides the desc. field are.... Using SLPPF and storing the info in a string and storing the string in a prim's "texture" field. i.e. llSetPrimitiveParams([ PRIM_TEXTURE, 3, "this is a storage area", <1.0, 1.0, 0.0>, ZERO_VECTOR, 0.0, PRIM_TEXTURE, 4, "this is also a storage area", <1.0, 1.0, 0.0>, ZERO_VECTOR, 0.0]); Using Void's Teacup code. http://wiki.secondlife.com/wiki/Teacup Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now