Jump to content

testgenord1

Resident
  • Posts

    146
  • Joined

  • Last visited

Everything posted by testgenord1

  1. Thanks for your reply! It solves the problem with the missing first question. Thanks again! ... and the repeated 2 questions in a row seem to be solved, too.
  2. Thanks for your suggestion. It enables the first question to be asked. However, it also seems to enable the repetition of a question twice in a row, in my tests. Thanks for the idea, anyway.
  3. Hi again! I made some additions to the script above, and partly ran into some new smaller problems: - I added a counter for the correct answers. Thus, the player is supposed to have won the complete quiz after 3 correct answers. It seems to work. (The dialog still has to be closed down by hand, now, through the "ignore" button. Any ideas of how to close down the dialog automatically will be appreciated.) - I also made the dialog repeat itself automatically after each correct reply. (This is a work-around, I guess, so I'm open for suggestions of improvement.) - Now the biggest problem: There was one little problem in the original script above, which is, the section preventing the repetition of the same question index = (index + 1 + (integer)llFrand(count - 1)) % count * 3; seems to prevent the first question in the list from being asked (at least, the first question was never asked, when I tested it). So I ended up changing it into index = (index + 1 + (integer)llFrand(count)) % count * 3; Now, all 3 questions are asked. Unfortunately, this seems to enable the repetition of the same question again. If you have ideas of how to change that, I will be very grateful for suggestions. Thank you very much in advance! Here is the script containing the counter: //by Mollymews, 10/16/2019 integer counter; list quiz = [ // question answer picks (buttons) the pipe | is the delimiter "What fraction equals 1/2?", "3/6", "1/6|2/6|3/6|4/6|5/6|6/6", "What fraction equals 3/5?", "9/15", "3/15|6/15|9/15|12/15|15/15", "What is 6 times 7?", "42", "36|42|67|76" ]; integer CHANNEL = -16; integer index; integer count; string answer; default { state_entry() { count = llGetListLength(quiz) / 3; llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) } touch_start(integer num) { // get a question not the same as the last question // this method is one way. Other methods of 'random' can be used also // index must be a value in range [0 < count] // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc index = (index + 1 + (integer)llFrand(count)) % count * 3; // get the question string question = llList2String(quiz, index); // get the answer // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc answer = llList2String(quiz, index + 1); // get the picks (buttons) // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc string picks = llList2String(quiz, index + 2); // parse the picks to a list on the pipe | delimiter // prepend a Dunno button list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []); // display dialog llDialog(llDetectedKey(0), question, buttons, CHANNEL); } listen(integer channel, string name, key id, string message) { if (message == answer) { llSay(0, "you the winner!"); // get a question not the same as the last question // this method is one way. Other methods of 'random' can be used also // index must be a value in range [0 < count] // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc index = (index + 1 + (integer)llFrand(count)) % count * 3; // get the question string question = llList2String(quiz, index); // get the answer // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc answer = llList2String(quiz, index + 1); // get the picks (buttons) // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc string picks = llList2String(quiz, index + 2); // parse the picks to a list on the pipe | delimiter // prepend a Dunno button list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []); // display dialog llDialog(id, question, buttons, CHANNEL); counter ++; if(counter == 3) { llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0); llSay(0, "You have won the quiz, " +name+ "."); llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT, 0)); llSetText(name+" has solved the quiz!",<1.0, 1.0, 1.0>,1.0); llResetScript(); } } else if (message == "Dunno") { llSay(0, "you egg !"); } else { llSay(0, "totes wrong !!!"); } } }
  4. Thank you so much for your help! This script is amazing. I've already learnt a lot just from going through the explanations. I seem to have gotten it to work. I'm posting it below the way I ended up doing it. Should there be some misunderstandings on my part, or should you find other possible improvements, feel free to comment more. I might come back here in case I have some more detailed questions. Thank you very much, again!😊👍 //by Mollymews, 10/16/2019 list quiz = [ // question answer picks (buttons) the pipe | is the delimiter "What fraction equals 1/2?", "3/6", "1/6|2/6|3/6|4/6|5/6|6/6", "What fraction equals 3/5?", "9/15", "3/15|6/15|9/15|12/15|15/15", "What is 6 times 7?", "42", "36|42|67|76" ]; integer CHANNEL = -16; integer index; integer count; string answer; default { state_entry() { count = llGetListLength(quiz) / 3; llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) } touch_start(integer num) { // get a question not the same as the last question // this method is one way. Other methods of 'random' can be used also // index must be a value in range [0 < count] // 3 is the width of the stride. 0 * 3 = 0. 1 * 3 = 3. 2 * 3 = 6. etc index = (index + 1 + (integer)llFrand(count)) % count * 3; // get the question string question = llList2String(quiz, index); // get the answer // 1 is the offest to the answer element. 0 + 1 = 1. 3 + 1 = 4. 6 + 1 = 7. etc answer = llList2String(quiz, index + 1); // get the picks (buttons) // 2 is the offset to the picks element. 0 + 2 = 2. 3 + 2 = 5. 6 + 2 = 8. etc string picks = llList2String(quiz, index + 2); // parse the picks to a list on the pipe | delimiter // prepend a Dunno button list buttons = ["Dunno"] + llParseString2List(picks, ["|"], []); // display dialog llDialog(llDetectedKey(0), question, buttons, CHANNEL); } listen(integer channel, string name, key id, string message) { if (message == answer) { llSay(0, "you the winner!"); } else if (message == "Dunno") { llSay(0, "you egg !"); } else { llSay(0, "totes wrong !!!"); } } }
  5. Hi! I'm trying to build a multiple-choice quiz using dialog menus. I'm running into three problems, which I can't seem to solve: 1. The dialog menu is supposed to automatically close down once all questions have been answered correctly, without clicking the "ignore" button (might not be possible in SL; not the main issue). 2. the main issue: If the question is answered correctly, a new dialog menu is supposed to be opened. If the question is answered wrongly, the dialog is supposed to go back to the initial menu, and so the player has to start all over again. In order to achieve this, I need a way to define the false replies in a convenient manner, without having to write down every single false answer. I tried using "else" as an alternative, but this does not work, because now also correct replies end up being counted as "false". 3. Is there a way to open the dialog menus, and thus the questions, in a random fashion? This would make the quiz more interesting. (But I guess that's complicated.) Since I'm still a beginner, I know the script is quite flawed. I apologize for this in advance, but this is all I have been able to accomplish so far. Here is the script: integer listen_handle; integer CHANNEL = -202; // dialog channel list question1 = ["1/4", "2/4" ]; list question2 = ["1/6","2/6","3/6","4/6","5/6","6/6"]; // a submenu default { state_entry() { llListen(CHANNEL, "", NULL_KEY, ""); // listen for dialog answers (from multiple users) } touch_start(integer total_number) { llSetTimerEvent(15); llDialog(llDetectedKey(0), "Which fraction equals 1/2?\n\n\n\n(Click 'ignore' to close the menu.)", question1, CHANNEL); // present dialog on click } listen(integer channel, string name, key id, string message) { if (message == "2/4") { llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0); llSay(0, "This is correct, " +name+ "."); llDialog(id, "Which fraction equals 1/3?\n\n\n\n(Click 'ignore' to close the menu.)", question2, CHANNEL); { if (message == "2/6") { llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c ",1.0); llSay(0, "This is correct, " +name+ "."); llGiveInventory(id,llGetInventoryName(INVENTORY_OBJECT, 0)); llSetText(name+" has solved the quiz!",<1.0, 1.0, 1.0>,1.0); llListenRemove(listen_handle); } else { llSay(0, "This is wrong, " +name+ "."); llDialog(id, "Which fraction equals 1/2?\n\n\n\n(Click 'ignore' to close the menu.)", question1, CHANNEL); } } } } timer() { llSetTimerEvent(0); llListenRemove(listen_handle); } }
  6. Thank you so much for your time and your explanations! I could never have come up with these ideas. These are great improvements and will help me a lot in the future. Again, thank you very much, I really appreciate this! edit: Through trial and error I noticed that we probably need llListenRemove( idListen); or llResetScript() at the end, because otherwise the listener will remain open indefinitely after the end of the timer. This means you could still answer the question although the timer has run already out. Is that right?
  7. Hi again! Thank you very much for your support. I chose Rolig Loon's method and it works fine. KT Kingsley's idea worked fine, too (I actually had used that idea at first, but forgot to define integer "user" as a global variable, preventing it from being used in the second state). I also liked Lucia Nightfire's idea quite a bit but I couldn't find out how to actually switch off the touch_start trigger using this. I don't actually need it at this point, but I like the idea, so, in case you could explain it to me, I would be grateful. Anyway, here is the adjusted script using Rolig Loon's ideas: key id; integer iTouched; default { touch_start(integer total_num) { if ( !iTouched ) // Be sure to make iTouched a global integer { iTouched = TRUE; llSay(0,"question"); id = llDetectedKey(0); llListen(0,"", id,""); llSetTimerEvent( 20.0 ); // For example, as a way to tell when the test has ended... } } listen(integer channel, string name, key id, string message) { if(message == "this is the correct answer") { llSay(0,"correct!"); } } timer() { iTouched = FALSE; // Ready for another test to start. llSetTimerEvent(0.0); } } Thanks again!
  8. Hi again! I'm writing a quiz script. The answers to the questions are typed into the chat. The quiz is supposed to be played by one player at a time only. This means the game must be restricted to the player who starts it first. Besides, I want the Public Channel to be open only, when really necessary, to prevent lagging. Hence, I decided to start the quiz by touch_start. Thus, the player's identity is stored through llDetectedKey, so only the player can reply to the questions and nobody else. The problem is, when one player is playing, a second player can trigger the touch_start event, too, and also start playing the game, disturbing the game of the first player. What I might need is a trick through which, for some time, the touch_start trigger is switched off, so that as long as the first player is playing, no one else can trigger it. Do you maybe have any idea of how to do this? There might also be differnt solutions to the problem. I'm posting the script below: default { touch_start(integer total_num) { llSay(0,"question"); key id = llDetectedKey(0); llListen(0,"", id,""); } listen(integer channel, string name, key id, string message) { if(message == "this is the correct answer") { llSay(0,"correct!"); } } } Thank you very much in advance!
  9. Thank you very much for your support! @Wulfie Reanimator: The script works nicely, thanks again. - The trick about integrating the sensor event in the listen event seems to be to put the sensor(integer num) completely outside of the listen(integer channel, string name, key id, string message) brackets. Is that right? - Thanks to your help I finally also was able to add a typecast to the script so that I can leave out the specific names of the target objects. Here is the script: rotation startrotation; key user; vector sit_position = <1.2, 0.0, 0.4>; vector sit_rotation = <0.0, 0.0, 0.0>; integer target_id; vector target_pos; default { state_entry() { llSetStatus(STATUS_PHANTOM, TRUE); rotation startrotation = llGetRot(); llSitTarget(sit_position, llEuler2Rot(sit_rotation * DEG_TO_RAD)); llForceMouselook(TRUE); } changed(integer change) { if (change & CHANGED_LINK) { key av = llAvatarOnSitTarget(); if (av) //evaluated as true if not NULL_KEY or invalid { llListen(PUBLIC_CHANNEL, "", NULL_KEY, ""); } } } listen(integer channel, string name, key id, string message) { message = llStringTrim(message, STRING_TRIM); if(message) { llSetStatus(STATUS_PHYSICS, TRUE); llSensor ("hypertext mobbing "+message,"",PASSIVE | ACTIVE,96.0,PI); } } sensor(integer num) { vector iTarget = llDetectedPos(0); vector offset = <-4,-6,-2.5>; iTarget += offset; target_id = llTarget(iTarget, 1.0); llMoveToTarget(iTarget,0.5); } at_target(integer tnum, vector targetpos, vector ourpos) { if (tnum == target_id) { llSetStatus(STATUS_PHYSICS, FALSE); llSetRot (startrotation); key user = llAvatarOnSitTarget(); if(user) { llSleep(1.0); //llForceMouselook(FALSE); llUnSit(user); llResetScript(); } } } } - Thanks for the idea about saving llResetScript. The last llResetScript still seems to be necessary to prevent you from getting "unsit", when trying to sit on the vehicle again. I also added a rotation correction in case the vehicle is accidentally rotated from hitting another object while moving. @Rolig Loon: Thanks for the additional idea about the llGetObjectDetails option. It works nicely. I had to split the vehicle script into two, though, but I guess that's fine. I'm posting it for other users potentially interested in this: vehicle script 1: //https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/ //the sit-starter: default { state_entry() { llSitTarget(<0.0, 0.0, 0.1>, ZERO_ROTATION); } changed(integer change) { if (change & CHANGED_LINK) { key av = llAvatarOnSitTarget(); if (av) { llRegionSay(-10001,"where?"); } } } } vehicle script 2: //https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/ //the mover script: default { state_entry() { llListen(-10001,"", NULL_KEY,""); } listen(integer channel, string name, key id, string message) { if(message == "here.") { list details = llGetObjectDetails(id, ([OBJECT_NAME, OBJECT_DESC, OBJECT_POS, OBJECT_ROT, OBJECT_VELOCITY, OBJECT_OWNER, OBJECT_GROUP, OBJECT_CREATOR])); vector position = llList2Vector(details,2); llSetRegionPos(position+<-1,0,0>); } } } destination script: //https://community.secondlife.com/forums/topic/441452-teleporter-using-object-names-instead-of-coordinate-vectors/ //destination script: default { state_entry() { llListen(-10001,"",NULL_KEY,""); } listen(integer channel, string name, key id, string message) { if(message == "where?") { llRegionSay(-10001, "here."); } } } Thanks again.
  10. Hi again! Thank you very much for your help. I still couldn't quite achieve it, so I ended up using a workaround, which is, you sit on a vehicle, which in turn is moved to objects having particular names through your chat messages. For each object name typed in, a different state in the script is initiated, which, unfortunately, is a bit clumsy. It works, though, at least on OSGRid / Opensim. I'm sorry it's a bit ugly, but I'm still a beginner. In case anyone would like to comment, I would appreciate that. Thanks again! key user; vector sit_position = <0.0, 0.0, 0.1>; vector sit_rotation = <0.0, 0.0, 0.0>; integer target_id; vector target_pos; default { state_entry() { llSitTarget(sit_position, llEuler2Rot(sit_rotation * DEG_TO_RAD)); llListen(PUBLIC_CHANNEL, "", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { message = llStringTrim(message, STRING_TRIM); if(message == "1") { state a; } if(message == "2") { state b; } else { llResetScript(); } } } state a { state_entry() { llSetStatus(STATUS_PHYSICS, TRUE); llSensor ("1","",PASSIVE,96.0,PI); } sensor(integer num) { vector iTarget = llDetectedPos(0); vector offset =<-3,0,0>; iTarget+=offset; target_id = llTarget(iTarget, 1.0); llMoveToTarget(iTarget,0.5); } at_target(integer tnum, vector targetpos, vector ourpos) { if (tnum == target_id) { llSetStatus(STATUS_PHYSICS, FALSE); key user = llAvatarOnSitTarget(); if(user) { llSleep(1.0); llUnSit(user); llResetScript(); } } } } state b { state_entry() { llSetStatus(STATUS_PHYSICS, TRUE); llSensor ("2","",PASSIVE,96.0,PI); } sensor(integer num) { vector iTarget = llDetectedPos(0); vector offset =<-3,0,0>; iTarget+=offset; target_id = llTarget(iTarget, 1.0); llMoveToTarget(iTarget,0.5); } at_target(integer tnum, vector targetpos, vector ourpos) { if (tnum == target_id) { llSetStatus(STATUS_PHYSICS, FALSE); key user = llAvatarOnSitTarget(); if(user) { llSleep(1.0); llUnSit(user); llResetScript(); } } } }
  11. Hi! I've got a script that uses the name of an object in order to teleport the avatar to that object, instead of using its coordinates. It uses llSensor in order to find the name of that particular object and then teleports the avatar to that object. This is quite convenient, particularly when you have to rearrange the object to a different location. The teleporter is initiated by touch_start. Now, I would like to change the teleporter in a way that it is initiated by llListen instead of touch_start, (e.g. on typing in "#1", the avatar is supposed to be teleported to the object named "#1" etc). However, I can't combine the llListen with the llSensor used in the script. Do you maybe have an idea of how to initiate the script using llListen? Thank you very much in advance! Here is the script: // Target Sensor Teleporter v0.1 by djphil (CC-BY-NC-SA 4.0) key user; default { state_entry() { llOwnerSay("Initialisation ..."); } touch_start(integer number) { user = llDetectedKey(0); llSensor("#1", "", PASSIVE, 96.0, PI); llSetText("#1", <1.0, 1.0, 1.0>, 1.0); } sensor(integer number) { vector det_pos = llDetectedPos(0); rotation det_rot = llDetectedRot(0); //osTeleportObject(llGetKey(), det_pos, det_rot, OSTPOBJ_NONE); osTeleportAgent(user, det_pos, ZERO_VECTOR); } no_sensor() { llSensor("#1", "", PASSIVE, 96.0, PI); llSetText("#1", <1.0, 1.0, 1.0>, 1.0); } }
  12. Hi! I've made an NPC that is supposed to approach you, once you've come within a certain distance of it. When it comes close to you, it is supposed to teleport you to a different location. Most if it already works. The only problem is, I cannot adjust the range within which the NPC is teleporting you. This means, the NPC teleports you once it is rezzed, no matter how great the distance is between the NPC and you. Does any of you maybe have an idea why this is? Here is the script (I shortened it down to the problematic part). Thank you very much in advance. key npc; vector npcPos1; vector npcPos; key Target; vector toucherPos; vector Pos; float Position; default { state_entry() { llSensorRepeat("","",AGENT,10,PI,1.0); } sensor(integer num) { integer i; for (i = 0; i < num; i ++) { Destination = llGetRegionName(); Target = llDetectedKey(i); TargetPos = llDetectedPos(i); Pos = llGetPos(); Position = llVecDist(toucherPos, npcPos); npcPos1 = llGetPos() + <0,0,0>; npc = osNpcCreate(NotecardName, "...", npcPos1, NotecardName); llSensorRemove(); toucherPos = llDetectedPos(i); npcPos = osNpcGetPos(npc); if (Position>1.0) { osNpcMoveToTarget(npc,toucherPos+<0,0,0>, OS_NPC_NO_FLY); } if (Position<3.0) { osTeleportAgent(Target, Destination, LandingPoint, LookAt); osNpcRemove(npc); } state default; } } }
  13. Thank you very much for your tip. That, apparently, was the problem. I deleted the states and now have only one script. It's still far from perfect, I guess, but it works, at least on OSGrid / OpenSim. Thank you very much again! integer tick; float move; vector oldPosition; list insults = [ "You are a loser! Ha, ha!", "You can't drive! He, he!", "I'm much better than you!", "I will win!", "You will lose! Ha, ha, ha!" ]; integer random; string insult() { integer count = llGetListLength(insults); random = (integer)llFrand((float)count); return llList2String(insults, random); } default { on_rez(integer start_param) { oldPosition = llGetPos(); llSetText("Johnny Craft ", <1.0,1.0,1.0>, 1.0); llListen(-799,"", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (message == "start") { llSay(0,"\n\n"+insult()); } if (message == "reset") { tick = 0; move = 0; llSetPos(oldPosition); llResetScript(); llSleep(5.0); llStopSound(); llDie(); } oldPosition = llGetPos(); llSetTimerEvent(10.0); } timer() { ++tick; move += 2; if (tick > 10) { llSetPos((oldPosition) + <move, 0.0, 0.0>); llRegionSay(-799,"reset"); llRegionSay(-798,"fireworks"); llLoopSound("cheer-hooter-01",1.0); llSay(0,"\n\nI'm the winner!!!!\n\nYou lose!!!\n\nHa, ha, ha!!!"); //llPlaySound("cheer-hooter-01",1.0); tick = 0; move = 0; llSleep(20.0); llRegionSay(-798,"fireworks"); llSleep(12.0); llSetPos(oldPosition); llSleep(5.0); llDie(); } else { llPlaySound("s_rev",1.0); llSleep(2.0); llSetPos((oldPosition) + <move, 0.0, 0.0>); } } }
  14. Continuation: I've added an automatic / npc car as an opponent and correspondingly adjusted the player's car script. The npc car just slowly drives forward in intervals through a timer / counter. Once npc the car has reached a certain number in the counter (here: "more than 10"), the npc car has won the race and the player has lost. Then, the npc car sends the message "reset" to the player's car, and the player's car stops and goes back to its initial position ("oldPosition"). Should the player answer all quiz questions correctly before this happens, the player has won. In that case, the player's car sends the message "reset" to the npc car, which now is supposed to stop moving and go back to its initial position ("oldPosition"). However, although the player's car reacts correctly on the message "reset", the npc car doesn't. It keeps moving regardless. Hence, I added an extra script, resetting the npc car script and setting it back to its initial position, which now works. Still, I'm curious why the message "reset" stops the player's car, but not the npc car, although the scripts as such are very similar. I'm posting the scripts below: player's car: // Simple Sensor Quizz I v0.1 by djphil (CC-BY-NC-SA 4.0) + Prim Computer v0.1 by djphil (CC-BY-NC-SA 4.0) list lSounds = [ "6e517cde-066f-455e-8c6b-f1c33be90dea", "611c9470-507e-4471-8ce2-5ed0962e4c85", "b1e78aa1-52b7-482f-a48a-57e3ddff81fc", "7b978d05-b3bd-4e6f-892f-92dc4845ddd8", "64319812-dab1-4e89-b1ca-5fc937b8d94a", "720ff3dd-8fc6-4523-9670-139df57527f3"]; integer tick; float move; vector oldPosition; list questions = [ "Was heißt auf Englisch: \n\nessen", "Was heißt auf Englisch: \n\ntrinken", "Was heißt auf Englisch: \n\ngehen \n(2 Buchstaben)", "Was heißt auf Englisch: \n\ngehen \n(4 Buchstaben)", "Was heißt auf Englisch: \n\nrennen", "Was heißt auf Englisch: \n\nfahren", "Was heißt auf Englisch: \n\nfliegen", "Was heißt auf Englisch: \n\nschlafen", "Was heißt auf Englisch: \n\ndenken", "Was heißt auf Englisch: \n\nmögen", "Was heißt auf Englisch: \n\nhaben", "Was heißt auf Englisch: \n\nverlieren", "Was heißt auf Englisch: \n\ngewinnen", "Was heißt auf Englisch: \n\nleben", "Was heißt auf Englisch: \n\nverstehen", "Was heißt auf Englisch: \n\nwissen" ]; list responses = [ "eat", "drink", "go", "walk", "run", "drive", "fly", "sleep", "think", "like", "have", "lose", "win", "live", "understand", "know" ]; integer random; string question() { integer count = llGetListLength(questions); random = (integer)llFrand((float)count); return llList2String(questions, random); } integer response(string response) { string csv = llList2String(responses, random); list buffer = llCSV2List(llToLower(csv)); if (~llListFindList(buffer, [llToLower(response)])) return TRUE; return FALSE; } default { on_rez(integer start_param) { oldPosition = llGetPos(); } touch_start(integer num) { llPlaySound("s_rev",1.0); llRegionSay(-799,"start"); state listening; } } state listening { state_entry() { llSetTimerEvent(8.0); } timer() { llSay(0, "\n\nSchreibe die Antwort in den Chat.\n\n" + question()); llListen(PUBLIC_CHANNEL,"", NULL_KEY, ""); llListen(-799,"", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (response(message) == TRUE) { llSay(0, "\n\nThat's correct, " + name + "!"); llPlaySound("s_rev",1.0); state moving; } if (message == "reset") { llSetPos(oldPosition); tick = 0; move = 0; llSleep(12.0); //llStopSound(); //state default; llDie(); } if (response(message) == FALSE) { tick = 0; move = 0; integer iWhichOne = (integer) llFrand( llGetListLength( lSounds ) ); llPlaySound( llList2String(lSounds, iWhichOne), 1.0); llSay(0,"\n\n\nThat's wrong, " + name + "! \n\n\n(Du musst wieder auf das Auto klicken.)"); llSetPos(oldPosition); key user = llAvatarOnSitTarget(); // Store the UUID of any agent sitting on the sit target. llUnSit(user); state default; } } } state moving { state_entry() { llSetTimerEvent(2.0); } timer() { ++tick; move += 4; if (tick > 5) { llSetPos((oldPosition) + <move, 0.0, 0.0>); tick = 0; move = 0; llRegionSay(-798,"fireworks"); llLoopSound("cheer-hooter-01",1.0); llSay(0,"\n\nYou have won!!!"); llRegionSay(-799,"reset"); llSleep(10.0); llRegionSay(-798,"fireworks"); llSleep(12.0); llSetPos(oldPosition); llSleep(5.0); //llStopSound(); //state default; llDie(); } else { llSetPos((oldPosition) + <move, 0.0, 0.0>); state listening; } } } npc car script: integer tick; float move; vector oldPosition; list insults = [ "You are a loser! Ha, ha!", "You can't drive! He, he!", "I'm much better than you!", "I will win!", "You will lose! Ha, ha, ha!" ]; integer random; string insult() { integer count = llGetListLength(insults); random = (integer)llFrand((float)count); return llList2String(insults, random); } default { on_rez(integer start_param) { oldPosition = llGetPos(); llSetText("Johnny Craft ", <1.0,1.0,1.0>, 1.0); state listening; } } state listening { state_entry() { llListen(-799,"", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (message == "start") { llSay(0,"\n\n"+insult()); state moving; } //if (message == "reset") //{ //tick = 0; //move = 0; //llSetPos(oldPosition); //llResetScript(); //llSleep(5.0); //llStopSound(); //llDie(); //} } } state moving { state_entry() { oldPosition = llGetPos(); llSetTimerEvent(18.0); } timer() { ++tick; move += 2; if (tick > 10) { llSetPos((oldPosition) + <move, 0.0, 0.0>); llRegionSay(-799,"reset"); llRegionSay(-798,"fireworks"); llLoopSound("cheer-hooter-01",1.0); llSay(0,"\n\nI'm the winner!!!!\n\nYou lose!!!\n\nHa, ha, ha!!!"); tick = 0; move = 0; llSleep(10.0); llRegionSay(-798,"fireworks"); llSleep(12.0); llSetPos(oldPosition); llSleep(5.0); //llStopSound(); llDie(); } else { llPlaySound("s_rev",1.0); llSetPos((oldPosition) + <move, 0.0, 0.0>); state moving; } } } extra npc car reset script: vector oldPosition; default { on_rez(integer start_param) { oldPosition = llGetPos(); llListen(-799,"", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (message == "reset") { llResetOtherScript("npc car script"); llSetPos(oldPosition); llSleep(12.0); llDie(); } } } Here is the part that isn't working in the npc car script: //if (message == "reset") //{ //tick = 0; //move = 0; //llSetPos(oldPosition); //llResetScript(); //llSleep(5.0); //llStopSound(); //state default; //llDie(); //} Do you maybe have any idea why this isn't working? Thank you very much in advance, and please excuse flaws in the scripts, I'm still learning.
  15. I eventually came up with a simpler version than the one above. It simply uses llSetPos and llGetPos. There is always room for improvement, so feel free to comment. Thanks very much for your help, roligloon! Here is the script: // Simple Sensor Quizz I v0.1 by djphil (CC-BY-NC-SA 4.0) + Prim Computer v0.1 by djphil (CC-BY-NC-SA 4.0) integer tick; float move; vector oldPosition; list questions = [ "Was heißt auf Englisch: \n\nessen", "Was heißt auf Englisch: \n\ntrinken", "Was heißt auf Englisch: \n\ngehen \n(2 Buchstaben)", "Was heißt auf Englisch: \n\ngehen \n(4 Buchstaben)", "Was heißt auf Englisch: \n\nrennen", "Was heißt auf Englisch: \n\nfahren", "Was heißt auf Englisch: \n\nfliegen", "Was heißt auf Englisch: \n\nschlafen", "Was heißt auf Englisch: \n\ndenken", "Was heißt auf Englisch: \n\nmögen", "Was heißt auf Englisch: \n\nhaben", "Was heißt auf Englisch: \n\nverlieren", "Was heißt auf Englisch: \n\ngewinnen", "Was heißt auf Englisch: \n\nleben", "Was heißt auf Englisch: \n\nverstehen", "Was heißt auf Englisch: \n\nwissen" ]; list responses = [ "eat", "drink", "go", "walk", "run", "drive", "fly", "sleep", "think", "like", "have", "lose", "win", "live", "understand", "know" ]; integer random; string question() { integer count = llGetListLength(questions); random = (integer)llFrand((float)count); return llList2String(questions, random); } integer response(string response) { string csv = llList2String(responses, random); list buffer = llCSV2List(llToLower(csv)); if (~llListFindList(buffer, [llToLower(response)])) return TRUE; return FALSE; } default { state_entry() { oldPosition = llGetPos(); } touch_start(integer num) { state listening; } } state listening { state_entry() { llSay(0, "\n\nSchreibe die Antwort in den Chat.\n\n" + question()); llListen(PUBLIC_CHANNEL,"", NULL_KEY, ""); llListen(-799,"", NULL_KEY, ""); } listen(integer channel, string name, key id, string message) { if (response(message) == TRUE) { llSay(0, "\n\nThat's correct, " + name + "!"); state moving; } else { tick = 0; move = 0; llPlaySound("64319812-dab1-4e89-b1ca-5fc937b8d94a",1.0); llSetPos(oldPosition); state default; } } } state moving { state_entry() { llSetTimerEvent(2.0); } timer() { ++tick; move += 2; if (tick > 2) { llSetPos((oldPosition) + <move, 0.0, 0.0>); llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c",1.0); llSay(0,"\n\nYou have won!!!"); tick = 0; move = 0; llSetPos(oldPosition); state default; } else { llSetPos((oldPosition) + <move, 0.0, 0.0>); state listening; } } }
  16. Hi again! Just tried out all improvements. Unfortunately, there is a different problem now, which is, with each correct reply to the questions, the linkset-vehicle moves along the negative y-axis, no matter how you change the coordinates by using the "move" variable. Besides, the linkset-vehicle does not return to its initial starting position after the "ticks" number of correct reply, but keeps moving in the same direction. I'm posting the script including the changes below. In case any of you can help, please let me know. 🙂 Thanks very much in advance! // Simple Sensor Quizz I v0.1 by djphil (CC-BY-NC-SA 4.0) + Prim Computer v0.1 by djphil (CC-BY-NC-SA 4.0) integer iSelf; integer tick; float move; list questions = [ "Was heißt auf Englisch: \n\nessen", "Was heißt auf Englisch: \n\ntrinken", "Was heißt auf Englisch: \n\ngehen \n(2 Buchstaben)", "Was heißt auf Englisch: \n\ngehen \n(4 Buchstaben)", "Was heißt auf Englisch: \n\nrennen", "Was heißt auf Englisch: \n\nfahren", "Was heißt auf Englisch: \n\nfliegen", "Was heißt auf Englisch: \n\nschlafen", "Was heißt auf Englisch: \n\ndenken", "Was heißt auf Englisch: \n\nmögen", "Was heißt auf Englisch: \n\nhaben", "Was heißt auf Englisch: \n\nverlieren", "Was heißt auf Englisch: \n\ngewinnen", "Was heißt auf Englisch: \n\nleben", "Was heißt auf Englisch: \n\nverstehen", "Was heißt auf Englisch: \n\nwissen" ]; list responses = [ "eat", "drink", "go", "walk", "run", "drive", "fly", "sleep", "think", "like", "have", "lose", "win", "live", "understand", "know" ]; integer random; string question() { integer count = llGetListLength(questions); random = (integer)llFrand((float)count); return llList2String(questions, random); } integer response(string response) { string csv = llList2String(responses, random); list buffer = llCSV2List(llToLower(csv)); if (~llListFindList(buffer, [llToLower(response)])) return TRUE; return FALSE; } default { state_entry() { llSetLinkPrimitiveParamsFast(1, [PRIM_POS_LOCAL, <0.0,0.0,0.0>]); } touch_start(integer num) { state listening; } } state listening { state_entry() { llSay(0, "\n\nSchreibe die Antwort in den Chat.\n\n" + question()); llListen(PUBLIC_CHANNEL,"", NULL_KEY, ""); llListen(-799,"", NULL_KEY, ""); //This can be used by a reset button. } listen(integer channel, string name, key id, string message) { if (response(message) == TRUE) { llSay(0, "That's correct, " + name + "!"); state moving; } else { llResetScript(); } } } state moving { state_entry() { llSetTimerEvent(2.0); iSelf = llGetNumberOfPrims(); // Be sure to declare iSelf as a global integer variable. } timer() { ++tick; move += 2; llSetLinkPrimitiveParamsFast(LINK_SET,[34,1,PRIM_POS_LOCAL,<0.0,move,0.0>, 34,iSelf,PRIM_POS_LOCAL,<0.0,move,0.0>]); if (tick > 3) { tick = 0; move = 0; llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c",1.0); llSleep(2.0); state default; } state listening; } }
  17. Thank you very much for your quick help! 🙂 I've only tested it in an offline version of OpenSim so far, and the online test might show different results, but it basically works. One little problem remained, and that is, not only the avatar, but also his / her vehicle is supposed to be moved, so the avatar seems to be "driving" the car. I used a workaround, even though it might not be the most elegant way: I simply repeated your line moving the avatar and this time I filled in the number for the actual child prim ("2") instead of "iSelf". (the line before the last line in the script). It seems to work so far, so I'll test it some more online during the week. Should I run into more trouble, I'll come around again. Thanks again! 🙂 state moving { state_entry() { llSetTimerEvent(2.0); iSelf = llGetNumberOfPrims(); // Be sure to declare iSelf as a global integer variable. } timer() { ++tick; move += 2; llSetLinkPrimitiveParamsFast(2, [PRIM_POS_LOCAL, <0.0, move, 0.0>]); llSetLinkPrimitiveParamsFast(iSelf, [PRIM_POS_LOCAL, <0.0, move, 0.5>]);
  18. Hi! I've made a vocabulary quiz game: - The player sits on a car. - He is asked vocabulary questions through the chat. - With each correct answer, he / she moves forward some meters on the car. - A wrong answer moves the car back to its initial starting position. - He / she plays against other players or NPCs / prims. - The player who goes through the finish line first wins. - Afterwards, the "car" goes back to its initial starting position. The script works (OpenSim/ OSGrid). One problem remains: I'm using llSetLinkPrimitiveParamsFast to change the position of the car. The script moves the child prim. Now, it is not possible to remain sitting on that moving child prim. The prim keeps moving without you sitting on it. It is possible to remain sitting on the moving root prim when the script moves the root prim instead of the child prim. In that case, though, the position of the root prim must be given in a fixed absolute vector at the beginning of the script, which is less flexible than the child-prim version, which uses a position relative to the root prim. I also tried out llSetKeyframdedMotion but using that, I haven't been able to return to the initial starting position at the end of the game. The ideal solution would be a child-prim which is "ride-able". Do you maybe have an idea of how to achieve that? Thank you very much in advance. Here is the script: // Simple Sensor Quizz I v0.1 by djphil (CC-BY-NC-SA 4.0) + Prim Computer v0.1 by djphil (CC-BY-NC-SA 4.0) integer tick; float move; list questions = [ "Was heißt auf Englisch: \n\nessen", "Was heißt auf Englisch: \n\ntrinken", "Was heißt auf Englisch: \n\ngehen \n(2 Buchstaben)", "Was heißt auf Englisch: \n\ngehen \n(4 Buchstaben)", "Was heißt auf Englisch: \n\nrennen", "Was heißt auf Englisch: \n\nfahren", "Was heißt auf Englisch: \n\nfliegen", "Was heißt auf Englisch: \n\nschlafen", "Was heißt auf Englisch: \n\ndenken", "Was heißt auf Englisch: \n\nmögen", "Was heißt auf Englisch: \n\nhaben", "Was heißt auf Englisch: \n\nverlieren", "Was heißt auf Englisch: \n\ngewinnen", "Was heißt auf Englisch: \n\nleben", "Was heißt auf Englisch: \n\nverstehen", "Was heißt auf Englisch: \n\nwissen" ]; list responses = [ "eat", "drink", "go", "walk", "run", "drive", "fly", "sleep", "think", "like", "have", "lose", "win", "live", "understand", "know" ]; integer random; string question() { integer count = llGetListLength(questions); random = (integer)llFrand((float)count); return llList2String(questions, random); } integer response(string response) { string csv = llList2String(responses, random); list buffer = llCSV2List(llToLower(csv)); if (~llListFindList(buffer, [llToLower(response)])) return TRUE; return FALSE; } default { state_entry() { llSetLinkPrimitiveParamsFast(2, [PRIM_POS_LOCAL, <0.5,0.0,0.0>]); } touch_start(integer num) { state listening; } } state listening { state_entry() { llSay(0, "\n\nSchreibe die Antwort in den Chat.\n\n" + question()); llListen(PUBLIC_CHANNEL,"", NULL_KEY, ""); llListen(-799,"", NULL_KEY, ""); //This can be used by a reset button. } listen(integer channel, string name, key id, string message) { if (response(message) == TRUE) { llSay(0, "That's correct, " + name + "!"); state moving; } else { llResetScript(); } } } state moving { state_entry() { llSetTimerEvent(2.0); } timer() { ++tick; move += 2; llSetLinkPrimitiveParamsFast(2, [PRIM_POS_LOCAL, <move, 0.0, 0.0>]); if (tick > 3) { tick = 0; move = 0; llPlaySound("ed124764-705d-d497-167a-182cd9fa2e6c",1.0); llSleep(5.0); state default; } state listening; } }
  19. Interesting. So the llGetSubString  would "cut off" the differing prefixes of the names of the two matching cards and thus turn the 'English card' into: "[ENG_]Texture_Boat" (="Texture_Boat") and the 'French' matching card into: "[FRA_]Texture_Boat" (="Texture_Boat") and then they would actually match. Did I get this right? I'll have a look at this. Just have to find out how to do this yet. Thanks!
  20. Hi! I've made a memory game using textures. The memory cards start off with their textures in the colour black. When you click on a card, the colour of the texture changes from black to white and it thus becomes visible. When you click on another card the same thing happens. When you happen to click on two matching cards (having the same texture), you get the feedback "Well done!" /"matching card found" or something similar. (matching cards: texture 1 and texture 1) What I would like to change, however is the following: I would like to use this memory game as a vocabulary exercise. One card is supposed to display an English word A second card is supposed to display the same word in a different language. There is a texture for the English word and another texture for the same word in, e.g., French. This means the script would have to be adjusted in the following way: The cards that match each other would not be cards having the same texture, but they would have different textures. (matching cards: texture English and texture French) I guess this is hard to achieve. Do you maybe have an idea of how to do this? Thank you very much in advance. //written by Rebecca Davis and dj phil 05/25/2019; //https://www.youtube.com/watch?v=lCHt7dCEqJA //https://forums.osgrid.org/viewtopic.php?f=5&t=6353 list pics = []; list used = []; list done = []; integer debug = FALSE; integer tries; list select = []; string pic1; key user; list success = []; list chosen = []; list players = []; string playerlist; key current; fillPics() { integer i; integer all = llGetInventoryNumber(INVENTORY_TEXTURE); if(debug)llOwnerSay((string)all+" textures found"); for(i=0; i<all; i=i+1) { string add = llGetInventoryName(INVENTORY_TEXTURE,i); pics = pics + add; if(debug)llOwnerSay("Adding Texture "+add+" to Pics List"); } } populate() { integer all = llGetNumberOfPrims( ); integer this = llGetLinkNumber(); integer picCount = llGetListLength(pics); picCount=picCount-1; list used = []; list done = []; if(debug) llOwnerSay((string)all+" Number of parts. The Root is "+(string)this); integer i; llSetLinkColor(this, <1,1,1>, ALL_SIDES); for(i=this; i<all; i=i+1) { string thisPic = picSelect(picCount); llSetLinkTexture(i+1,thisPic,ALL_SIDES); llSetLinkColor(i+1, <0,0,0>, ALL_SIDES); //llSetLinkColor(i+1, <0,0,0>, ALL_SIDES); } } string picSelect(integer picCount) { user = llGetOwner(); integer nope = 1; string picName; while(nope != -1) { integer choose = llRound(llFrand(picCount)); picName= llList2String(pics,choose); nope = llListFindList(done,[picName]); integer last = llListFindList(used,[picName]); if(last != -1) done = done + picName; else used = used + picName; } return picName; } chooser(integer box) { string name = llKey2Name(user); llSetLinkColor(box,<1,1,1>, ALL_SIDES); select = select+box; if(llGetListLength(select)>1) { string pic2 = texture(box); if(pic1 == pic2) { llSay(0,"Well done, "+name+"!"+"\n\n"); chosen = chosen + box; box = llList2Integer(select,0); chosen = chosen + box; } else { //llSay(0,"Sorry that is not a match"); llSleep(3); if(llListFindList(chosen,[box]) == -1)llSetLinkColor(box,<0,0,0>, ALL_SIDES); box = llList2Integer(select,0); if(llListFindList(chosen,[box]) == -1)llSetLinkColor(box,<0,0,0>, ALL_SIDES); integer place = llListFindList(players, [current]); place = place +1; if(place < llGetListLength(players) ) current = llList2Key(players,place); else current = llList2Key(players,0); llSetText(playerlist+"\n\n It is "+llKey2Name(current)+"'s turn.\n\n", <1,1,1>, 1); } //llSay(0,name+" is done"); llSay(0,"Next player, please.\n\n"); select = []; pic1 = ""; return; } else { pic1 = texture(box); } } string texture(integer box) { list params = llGetLinkPrimitiveParams(box,[ PRIM_TEXTURE, 0]); string get = llList2String(params,0); return get; } add(key who) { players = players + who; string PlayersShow = ""; integer i; for(i=0; i<llGetListLength(players); i=i+1) { PlayersShow = PlayersShow + llKey2Name(llList2Key(players,i)); } playerlist = "players:\n"+PlayersShow; llSetText("players "+PlayersShow+"\nClick to join the game.\n\n", <1,1,1>, 1); } default { state_entry() { fillPics(); populate(); //llSay(0,"Click the board to sign up for this round"); llListen(0,"",NULL_KEY,"start"); llListen(0,"",NULL_KEY,"reset"); //llSetText("Current Players \n None \n \nclick to join game", <1,1,1>, 1); } listen(integer chan, string what, key who, string msg) { if(msg == "start")state play; else if(msg == "reset")llResetScript(); } touch_start(integer clicked) { add(llDetectedKey(0)); state play; } } state play { state_entry() { llSay(0,"Starting the game"+"\n\n"); llListen(0,"",NULL_KEY,"reset"); current = llList2Key(players,0); llSetText(playerlist+"\n\n It is "+llKey2Name(current)+"'s turn.\n\n", <1,1,1>, 1); } listen(integer chan, string what, key who, string msg) { if(msg == "reset")llResetScript(); } touch_start(integer total_number) { key clicked = llDetectedKey(0); if(clicked != current) { llInstantMessage(clicked,"Sorry, it is not your turn.\n\n"); return; } if(clicked != user) { llInstantMessage(clicked,"It is not your turn.\n\n"); return; } integer box = llDetectedLinkNumber(0); if(llListFindList(chosen,[box]) == -1) chooser(box); llSetTimerEvent(120); } timer() { llResetScript(); } }
  21. Hi again. Yes, this is where I got the script from. Sorry about the messy script. So, thank you all very much for taking your time and your patience. Thanks to your help I got the scripts to work. At the top I added the global variable list KFMcommand; I hope this was correct. At least it worked after that. For other users possibly interested in this, I'm adding my final version below. There is probably still room for improvement, so feel free to comment if you like. Here is the new version of the script of the moving part: (The other one I basically left as it was.) // KFM Vocabulary Memory Game Reciever v0.2 by djphil (CC-BY-NC-SA 4.0) and Qie Niangao //https://community.secondlife.com/forums/topic/434279-llsetkeyframedmotion-forward-and-back/ list KFMcommand;//changed original script here. integer canal = -123654789; integer tempo = 5; integer echo; integer count; integer power; string lang; string word; string trad; string prim; vector pos; rotation rot; 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 buffer = llCSV2List(llGetObjectName()); if (llGetListLength(buffer) == 2) { lang = llStringTrim(llList2String(buffer, 0), STRING_TRIM); prim = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim name detected"); return; } buffer = llCSV2List(llGetObjectDesc()); if (llGetListLength(buffer) == 2) { word = llStringTrim(llList2String(buffer, 0), STRING_TRIM); trad = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim desc detected"); return; } llSetText("state: ready", <1.0, 1.0, 1.0>, 1.0); llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX ]); } touch_start(integer number) { llListenRemove(echo); count = 0; if (power =! power) { echo = llListen(canal, prim + "," + lang, NULL_KEY, ""); llSetTimerEvent(0.1); } else { llSetTimerEvent(0.0); } llSetText("state: ready", <1.0, 1.0, 1.0>, 1.0); } listen(integer channel, string name, key id, string message) { list buffer = llCSV2List(name); if (llGetListLength(buffer) == 2) { name = llList2String(buffer, 0); if (name == prim) { buffer = llCSV2List(message); if (llGetListLength(buffer) == 3) { message = llList2String(buffer, 0); pos = (vector)llList2String(buffer, 1);//changed original script here. rot = llList2Rot(buffer, 1); if (message == trad) { llListenRemove(echo); power =! power; llShout(canal, message); state move; } } } } } timer() { llSetTimerEvent(1.0); llShout(canal, word + "," + (string)llGetPos() + "," + (string)llGetRot()); if (count > tempo) { llResetScript(); } llSetText("time left: " + (tempo - count), <1.0, 1.0, 1.0>, 1.0); ++count; } } state move//changed original script here. { state_entry() { llOwnerSay(llGetScriptName()+" in move state with pos = "+(string)pos); rotation spin = NormRot(llEuler2Rot(<90.0, 0.0, 0.0> * DEG_TO_RAD)); KFMcommand = [ <0.0, 0.0, 1.0> * llGetRot(), ZERO_ROTATION, 0.5, pos - llGetPos(), ZERO_ROTATION, 1.0, ZERO_VECTOR, spin, 0.5 ]; llSetKeyframedMotion(KFMcommand, [KFM_MODE, KFM_FORWARD]); llSleep(5); } touch_end(integer num_detected) { llShout(canal, word + "," + (string)llGetPos() + "," + (string)llGetRot()); llSetKeyframedMotion(KFMcommand, [KFM_MODE, KFM_REVERSE]); llShout(canal, trad); //llSetText("lang: " + lang + "\nword: " + word + "\ntrad: " + trad, <1.0, 1.0, 1.0>, 1.0); llResetScript(); } }
  22. Thank you for your reply. The scripts do work. I forgot to mention that you have to give a particular name and description to both prims. For example: prim 1: name: English,German description: Vocabulary,Vokabular prim 2: name: German,English description: Vokabular,Vocabulary
  23. Hi! I've got a script that makes a prim move on top of a different prim when clicked on, and then automatically move back to its initial position. I would like the prim to remain on top of that prim and only move back when clicked on a second time. The movement has to be split into two parts (the back-movement part seems to go into the timer below), and then a touch_start event has to be built into it, but I haven't been able to achieve this. Maybe you have some ideas? Here is the part of the script containing the movement: state move { state_entry() { rotation spin = NormRot(llEuler2Rot(<0.0, 0.0, 180.0> * DEG_TO_RAD)); llSetTimerEvent(0.1); llSetKeyframedMotion([ <0.0, 0.0, 1.0> * llGetRot(), ZERO_ROTATION, 0.5, pos - llGetPos() + ZERO_VECTOR * llGetRot(), ZERO_ROTATION, 1.0, ZERO_VECTOR, spin, 0.5, ZERO_VECTOR, ZERO_ROTATION, 1.0, llGetPos() - pos + ZERO_VECTOR * llGetRot(), ZERO_ROTATION, 1.0, -<0.0, 0.0, 1.0> * llGetRot(), ZERO_ROTATION, 0.5, ZERO_VECTOR, spin, 0.5 ], [KFM_MODE, KFM_FORWARD]); } timer() { llSetTimerEvent(1.0); llShout(canal, word + "," + (string)llGetPos() + "," + (string)llGetRot()); if (count > 5) { llShout(canal, trad); llResetScript(); } llSetText("lang: " + lang + "\nword: " + word + "\ntrad: " + trad, <1.0, 1.0, 1.0>, 1.0); ++count; } } Thank you very much in advance. I'm adding the complete 2 scripts for context: 1. The script of the prim doing the movement: // KFM Vocabulary Memory Game Reciever v0.2 by djphil (CC-BY-NC-SA 4.0) integer canal = -123654789; integer tempo = 5; integer echo; integer count; integer power; string lang; string word; string trad; string prim; vector pos; rotation rot; 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 buffer = llCSV2List(llGetObjectName()); if (llGetListLength(buffer) == 2) { lang = llStringTrim(llList2String(buffer, 0), STRING_TRIM); prim = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim name detected"); return; } buffer = llCSV2List(llGetObjectDesc()); if (llGetListLength(buffer) == 2) { word = llStringTrim(llList2String(buffer, 0), STRING_TRIM); trad = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim desc detected"); return; } llSetText("lang: " + lang + "\nword: " + word + "\nstate: ready", <1.0, 1.0, 1.0>, 1.0); llSetLinkPrimitiveParamsFast(LINK_THIS, [ PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX ]); } touch_start(integer number) { llListenRemove(echo); count = 0; if (power =! power) { echo = llListen(canal, prim + "," + lang, NULL_KEY, ""); llSetTimerEvent(0.1); } else { llSetTimerEvent(0.0); } llSetText("lang: " + lang + "\nword: " + word + "\nstate: ready", <1.0, 1.0, 1.0>, 1.0); } listen(integer channel, string name, key id, string message) { list buffer = llCSV2List(name); if (llGetListLength(buffer) == 2) { name = llList2String(buffer, 0); if (name == prim) { buffer = llCSV2List(message); if (llGetListLength(buffer) == 3) { message = llList2String(buffer, 0); pos = llList2Vector(buffer, 1); rot = llList2Rot(buffer, 1); if (message == trad) { llListenRemove(echo); power =! power; llShout(canal, message); state move; } } } } } timer() { llSetTimerEvent(1.0); llShout(canal, word + "," + (string)llGetPos() + "," + (string)llGetRot()); if (count > tempo) { llResetScript(); } llSetText("lang: " + lang + "\nword: " + word + "\ntimeleft: " + (tempo - count), <1.0, 1.0, 1.0>, 1.0); ++count; } } state move { state_entry() { rotation spin = NormRot(llEuler2Rot(<0.0, 0.0, 180.0> * DEG_TO_RAD)); llSetTimerEvent(0.1); llSetKeyframedMotion([ <0.0, 0.0, 1.0> * llGetRot(), ZERO_ROTATION, 0.5, pos - llGetPos() + ZERO_VECTOR * llGetRot(), ZERO_ROTATION, 1.0, ZERO_VECTOR, spin, 0.5, ZERO_VECTOR, ZERO_ROTATION, 1.0, llGetPos() - pos + ZERO_VECTOR * llGetRot(), ZERO_ROTATION, 1.0, -<0.0, 0.0, 1.0> * llGetRot(), ZERO_ROTATION, 0.5, ZERO_VECTOR, spin, 0.5 ], [KFM_MODE, KFM_FORWARD]); } timer() { llSetTimerEvent(1.0); llShout(canal, word + "," + (string)llGetPos() + "," + (string)llGetRot()); if (count > 5) { llShout(canal, trad); llResetScript(); } llSetText("lang: " + lang + "\nword: " + word + "\ntrad: " + trad, <1.0, 1.0, 1.0>, 1.0); ++count; } } 2. ... and the script of the other prim: // KFM Vocabulary Memory Game Emitter v0.2 by djphil (CC-BY-NC-SA 4.0) integer canal = -123654789; integer tempo = 5; integer echo; integer count; integer power; string lang; string word; string trad; string prim; default { state_entry() { list buffer = llCSV2List(llGetObjectName()); if (llGetListLength(buffer) == 2) { lang = llStringTrim(llList2String(buffer, 0), STRING_TRIM); prim = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim name detected"); return; } buffer = llCSV2List(llGetObjectDesc()); if (llGetListLength(buffer) == 2) { word = llStringTrim(llList2String(buffer, 0), STRING_TRIM); trad = llStringTrim(llList2String(buffer, 1), STRING_TRIM); } else { llOwnerSay("Error: Bad prim desc detected"); return; } llSetText("lang: " + lang + "\nword: " + word + "\nstate: ready", <1.0, 1.0, 1.0>, 1.0); } touch_start(integer number) { llListenRemove(echo); count = 0; if (power =! power) { echo = llListen(canal, prim + "," + lang, NULL_KEY, ""); llSetTimerEvent(0.1); } else { llSetTimerEvent(0.0); } llSetText("lang: " + lang + "\nword: " + word + "\nstate: ready", <1.0, 1.0, 1.0>, 1.0); } listen(integer channel, string name, key id, string message) { list buffer = llCSV2List(name); if (llGetListLength(buffer) == 2) { name = llList2String(buffer, 0); if (name == prim) { if (message == word) { llSetTimerEvent(0.0); state move; } } } } timer() { llSetTimerEvent(1.0); llShout(canal, word + "," +(string)llGetPos() + "," + (string)llGetRot()); if (count > tempo) { llResetScript(); } llSetText("lang: " + lang + "\nword: " + word + "\ntimeleft: " + (tempo - count), <1.0, 1.0, 1.0>, 1.0); ++count; } } state move { state_entry() { llListenRemove(echo); echo = llListen(canal, prim + "," + lang, NULL_KEY, ""); llSetText("lang: " + lang + "\nword: " + word + "\ntrad: " + trad, <1.0, 1.0, 1.0>, 1.0); } listen(integer channel, string name, key id, string message) { list buffer = llCSV2List(name); if (llGetListLength(buffer) == 2) { name = llList2String(buffer, 0); if (name == prim) { if (message == word) { llResetScript(); } } } } }
  24. Thanks for the suggestion! I'll try that.😊
  25. Hi again! Thank you very much for your support! Sorry about the messy script. Your script looks a lot nicer this way Btw. do you know a good editor for lsl scripts that puts them in a nicer format and maybe also helps to debug scripts?. The script isn't originally mine. I kept the lists in place since it is also possible to shoot at the zombie with a gun and kill it this way. I just don't want to use this in school. Maybe somebody else has some use for this. I just kept he lookat values the way they were. <1,1,1> means a 180 twist? I just tried out different variations but I couldn't see much difference. Thanks very much again for your help!
×
×
  • Create New...