00b02c Posted October 23, 2021 Share Posted October 23, 2021 (edited) Hey! I decided to try to make such a wearable "device", which would allow when another avatar appears in a certain radius, my avatar starts moving in the opposite direction. As if he was running away from other avatars. Not sure how logical it sounds ... I figured I needed to start with a sensor event and a ... llMoveToTarget(llGetPos() - <some_vector???>, 0.0); but I got stuck on that. Please tell me where to go next? Well, in the sense of how to run back for about twenty meters and stop until someone approaches again. Or can he push himself away? I know this is a bit wild, but still. Edited October 23, 2021 by 00b02c :) Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 23, 2021 Share Posted October 23, 2021 Ooh, fun. There are advantages and disadvantages to both, but I generally prefer llSetForce() over llMoveToTarget when possible. So, what you want to do is apply a force to yourself in a direction facing away from the other avatar. Forces can be thought about like little arrows, that move things form their tail to their head. a force between two points is as simple as vector force = head - tail; and in this case the head would be your position, and the tail the position of the person you're running away from: vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0),[OBJECT_POS]),0); but the strength of a force is proportional to how long it is. if you were to use that, you would be pushed very hard when far from your friend, and very little when close by, which is the opposite of what you want. to make things simple you could make the force always the same by setting its length to one (which is called 'normalizing' it) and multiplying by a desired length: force = llVecNorm(force)*10; Putting that all together: (untested, I may have bugs.) default() { state_entry() { llSensorRepeat("","",AGENT_BY_USERNAME,12,PI,1.0); } sensor(integer n) { vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0),[OBJECT_POS]),0); force = llVecNorm(force)*10; llSetForce(force,FALSE); } no_sensor() { llSetForce(<0,0,0>,FALSE); } } 2 2 Link to comment Share on other sites More sharing options...
animats Posted October 23, 2021 Share Posted October 23, 2021 This is a surprisingly hard problem. My NPCs will try to get out of the way of a vehicle, but they're more sluggish doing so than I would like because they have to do multiple llCastRay calls to find open space. 2 Link to comment Share on other sites More sharing options...
Profaitchikenz Haiku Posted October 23, 2021 Share Posted October 23, 2021 (edited) 9 hours ago, Quistess Alpha said: Ooh, fun. There are advantages and disadvantages to both, but I generally prefer llSetForce() over llMoveToTarget when possible. So, what you want to do is apply a force to yourself in a direction facing away from the other avatar. If the viewer is rlv-enabled, you can also work out the angle through which the avatar is to turn and then get them to face the direction they are moving using llOwnerSay("@setrot') Edited October 23, 2021 by Profaitchikenz Haiku 1 Link to comment Share on other sites More sharing options...
Profaitchikenz Haiku Posted October 23, 2021 Share Posted October 23, 2021 7 hours ago, animats said: This is a surprisingly hard problem. Hmm, every time I visit your cafe, the NPCs come running out to greet me but when they see who it is, they turn and run away as fast as possible. They seem to know exactly how to do it @) 1 1 Link to comment Share on other sites More sharing options...
00b02c Posted October 23, 2021 Author Share Posted October 23, 2021 (edited) 12 hours ago, Quistess Alpha said: Ooh, fun. There are advantages and disadvantages to both, but I generally prefer llSetForce() over llMoveToTarget when possible. So, what you want to do is apply a force to yourself in a direction facing away from the other avatar. Forces can be thought about like little arrows, that move things form their tail to their head. a force between two points is as simple as vector force = head - tail; and in this case the head would be your position, and the tail the position of the person you're running away from: vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0),[OBJECT_POS]),0); but the strength of a force is proportional to how long it is. if you were to use that, you would be pushed very hard when far from your friend, and very little when close by, which is the opposite of what you want. to make things simple you could make the force always the same by setting its length to one (which is called 'normalizing' it) and multiplying by a desired length: force = llVecNorm(force)*10; Putting that all together: (untested, I may have bugs.) default() { state_entry() { llSensorRepeat("","",AGENT_BY_USERNAME,12,PI,1.0); } sensor(integer n) { vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0),[OBJECT_POS]),0); force = llVecNorm(force)*10; llSetForce(force,FALSE); } no_sensor() { llSetForce(<0,0,0>,FALSE); } } Hey! Thanks so much for the kindly provided script! It works as it should, I noticed that it even works like a HUD, which is very convenient! I just tested it in a crowded place and it looks pretty funny! Edited October 23, 2021 by 00b02c 1 Link to comment Share on other sites More sharing options...
Mollymews Posted October 23, 2021 Share Posted October 23, 2021 1 hour ago, 00b02c said: I just tested it in a crowded place and it looks pretty funny! your next challenge is to mod the script so that the sensor only starts when your avatar is not moving under your manual control. This way you can move yourself normally and when in running away mode you can manually run away in other directions as well fa way to trigger when to start/stopthe sensor is with: http://wiki.secondlife.com/wiki/LlTakeControls 1 1 Link to comment Share on other sites More sharing options...
Innula Zenovka Posted October 23, 2021 Share Posted October 23, 2021 11 hours ago, animats said: This is a surprisingly hard problem. My NPCs will try to get out of the way of a vehicle, but they're more sluggish doing so than I would like because they have to do multiple llCastRay calls to find open space. Could they not use pathfinding and llEvade? 1 Link to comment Share on other sites More sharing options...
00b02c Posted October 23, 2021 Author Share Posted October 23, 2021 (edited) 1 hour ago, Mollymews said: your next challenge is to mod the script so that the sensor only starts when your avatar is not moving under your manual control. This way you can move yourself normally and when in running away mode you can manually run away in other directions as well fa way to trigger when to start/stopthe sensor is with: http://wiki.secondlife.com/wiki/LlTakeControls Thank you! I tried this but it doesn't seem to have any effect on me. Something's missing... default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS); } run_time_permissions(integer perm) { llSensorRepeat("", "", AGENT_BY_USERNAME, 12, PI, 1.0); if (PERMISSION_TAKE_CONTROLS & perm) { llTakeControls( CONTROL_FWD | CONTROL_BACK | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT | CONTROL_UP | CONTROL_DOWN | CONTROL_LBUTTON | CONTROL_ML_LBUTTON, TRUE, TRUE); } } control(key id, integer level, integer edge) { integer start = level & edge; integer end = ~level & edge; integer held = level & ~edge; integer untouched = ~(level | edge); //llOwnerSay(llList2CSV([level, edge, start, end, held, untouched])); } sensor(integer n) { vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0), [OBJECT_POS]), 0); force = llVecNorm(force) * 10; llSetForce(force, FALSE); } no_sensor() { llSetForce( < 0, 0, 0 > , FALSE); } } Edited October 23, 2021 by 00b02c Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 23, 2021 Share Posted October 23, 2021 7 hours ago, Profaitchikenz Haiku said: If the viewer is rlv-enabled, you can also work out the angle through which the avatar is to turn and then get them to face the direction they are moving using llOwnerSay("@setrot') A naive implementation of that will have the avatar walk backwards some of the time, and Avatars face the direction they are moving (or backwards if things go wonky) by default anyway. 1 1 Link to comment Share on other sites More sharing options...
Mollymews Posted October 24, 2021 Share Posted October 24, 2021 9 hours ago, 00b02c said: Something's missing... you did get some of the pieces in place so good on you. To progress you further then, the next steps go something like this set up a global variable integer Flee when Flee is TRUE the sensor is On. When Flee is FALSE the sensor is Off in the run_time_permissions event set Flee to FALSE take controls set up a touch_start event. In this event toggle Flee TRUE or FALSE on successive touches. Flee = !Flee; (this lets you start/stop Flee mode manually) if Flee is TRUE start the sensor else Flee is FALSE stop the sensor in the control event use integer start (=keydown) to set Flee to FALSE. OnKeyDown you are moving yourself use integer end (=keyup) to set Flee to TRUE. OnKeyUp you are not moving yourself start/stop the sensor on Flee (as above) set up a attach event when script is attached, request permissions 1 Link to comment Share on other sites More sharing options...
Innula Zenovka Posted October 25, 2021 Share Posted October 25, 2021 On 10/23/2021 at 1:52 AM, Quistess Alpha said: There are advantages and disadvantages to both, but I generally prefer llSetForce() over llMoveToTarget when possible. I'm primarily used to llMoveToTarget because I like the degree of control it gives me, but I'm always looking to expand my skillset. How readily can I use llSetForce to maintain a constant and known speed (e.g. I want to run away from someone every time I see them, so I want to move at 5.13 metres a second)? Or is that a use case for llMoveToTarget and stopping it in the not at target event rather than waiting for damping to cut in? Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 25, 2021 Share Posted October 25, 2021 2 hours ago, Innula Zenovka said: How readily can I use llSetForce to maintain a constant and known speed (e.g. I want to run away from someone every time I see them, so I want to move at 5.13 metres a second)? Or is that a use case for llMoveToTarget and stopping it in the not at target event rather than waiting for damping to cut in? If you are (an attachment on) an avatar on the ground, then set force will probably be fairly consistent for you; you will quickly reach a maximum speed due to friction, and that speed will basically be the same everywhere. the short time to reach maximum speed to me feels a bit nicer than automatically jerking to top speed (testing may be required to determine the maximum speed a priori. ) If you're flying or go over a hill though, well, let's just say space is weird, and there's no air friction in SL. 1 Link to comment Share on other sites More sharing options...
Innula Zenovka Posted October 25, 2021 Share Posted October 25, 2021 29 minutes ago, Quistess Alpha said: If you are (an attachment on) an avatar on the ground, then set force will probably be fairly consistent for you; you will quickly reach a maximum speed due to friction, and that speed will basically be the same everywhere. the short time to reach maximum speed to me feels a bit nicer than automatically jerking to top speed (testing may be required to determine the maximum speed a priori. ) If you're flying or go over a hill though, well, let's just say space is weird, and there's no air friction in SL. Thanks. What I'm not really understanding is how I determine what the maximum speed should be. In your example, you have vector force = llGetPos() - llList2Vector(llGetObjectDetails(llDetectedKey(0),[OBJECT_POS]),0); force = llVecNorm(force)*10; llSetForce(force,FALSE); I understand what it's doing, but I don't understand the multiplier. By what do I multiply llVecNorm(force) if I want to run away at 5.13 metres/second, the default running speed? Or is this a case for llMove2Target? Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 25, 2021 Share Posted October 25, 2021 26 minutes ago, Innula Zenovka said: By what do I multiply llVecNorm(force) if I want to run away at 5.13 metres/second, the default running speed? Or is this a case for llMove2Target? Yes, if you want an exact speed, llMove2Target would probably do you better, with set force, it's easiest to just guess and check different values for the factor. 1 Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 25, 2021 Share Posted October 25, 2021 (edited) 46 minutes ago, Innula Zenovka said: By what do I multiply llVecNorm(force) if I want to run away at 5.13 metres/second, the default running speed? Or is this a case for llMove2Target? Actually, For my own edification, when using llMoveToTarget, what point should I move to and with what tau if I want to move forward (direction <1,0,0>) at 5.13 meters per second? Do you just use llMove2Target(5.13*llRot2Fwd(llGetRot()),1.0); ? I'd expect that to be a little off due to how the damping works. Oh and for the force method, Just remembering that you can damp your velocity to a maximum pretty easily: vector vel = llGetVel(); if(vel*vel>= max_speed*max_speed) { llSetVelocity(llVecNorm(vel)*max_speed); } Edited October 25, 2021 by Quistess Alpha Link to comment Share on other sites More sharing options...
Innula Zenovka Posted October 25, 2021 Share Posted October 25, 2021 1 hour ago, Quistess Alpha said: Actually, For my own edification, when using llMoveToTarget, what point should I move to and with what tau if I want to move forward (direction <1,0,0>) at 5.13 meters per second? Generally, I use llMoveToTarget to move in the right direction, calculating the tau on the basis my target is much further away than my intended destination, and then stopping and starting things in either one of the *_target events or a timer or whatever is convenient. Now we've got KFM and pathfinding that technique isn't so necessary, of course, but sometimes it's useful. float fSpeed = 5.13;// default running speed float fTau = 2.0; integer iToggle; vector vTargetPos; default { state_entry() { } touch_start(integer total_number) { if(llGetAttached()){ if(iToggle =!iToggle){ vTargetPos = llGetPos()+<(fSpeed*fTau),0.0,0.0>*llGetRot(); llMoveToTarget(vTargetPos,fTau); llSetTimerEvent(0.5); } else{ llSetTimerEvent(0.0); llStopMoveToTarget(); } } } timer(){ llStopMoveToTarget(); vTargetPos = llGetPos()+<(fSpeed*fTau),0.0,0.0>*llGetRot(); llMoveToTarget(vTargetPos,fTau); } } Link to comment Share on other sites More sharing options...
Quistess Alpha Posted October 25, 2021 Share Posted October 25, 2021 17 minutes ago, Innula Zenovka said: float fTau = 2.0; // ... llSetTimerEvent(0.5); Ah, so would it be correct to say fTau should be 1/timer_frequency to have the speed be correct? Link to comment Share on other sites More sharing options...
Innula Zenovka Posted October 25, 2021 Share Posted October 25, 2021 15 minutes ago, Quistess Alpha said: Ah, so would it be correct to say fTau should be 1/timer_frequency to have the speed be correct? Yes, if you're running it on a timer. 1 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