Jump to content
  • 0

LSL scripting problem, multiple collisions


SapphicFancy
 Share

You are about to reply to a thread that has been inactive for 3163 days.

Please take a moment to consider if this thread is worth bumping.

Question

 

// sometimes, for no apparent reason, the ball will return twice
// since the ball return function is only called from the collision event
// i have to deduce that its some sort of multi-collision that is
// remembered and recalled

// ive tried resetscript, but that does not stop it

// ive tried resetting the " numberOfCollisions" to zero and that does not stop it

// BOWLING BALL by gwen
//
// with return or play capabilities
//
//


vector motionless; // where am i now, have i moved?
vector returnToZ = < 0, 0, 63 >; // going back up for another roll
vector returnToXY = < -49, -69, 0 >; // move across to starting point
vector tempHolding = <181, 202, 4002>; // so the person in the ball can see the pins fall

 

ballReturn() // this returns the ball to the start point
{
llSetStatus(STATUS_PHYSICS, FALSE); // must shut off physical for llSetKeyframedMotion
llSetRegionPos(tempHolding); // destination < 132,133, 4065 >
llSleep(10); // rest here a moment, just for the heck of it
llSetKeyframedMotion([ returnToZ, ZERO_ROTATION, 7.0 ],[ ]); // rise to start elevation
llSleep(7); // have to use this to keep all motions from misfiring
llSetKeyframedMotion([ returnToXY, ZERO_ROTATION, 7.0 ],[ ]); // move to start xy point
llSleep(7);
llSetKeyframedMotion([ ],[ ]); // stop the keyframedmotion
llSetStatus(STATUS_PHYSICS, TRUE); // return to physical status
}

// sometimes, for no apparent reason, the ball will return twice
// since this function is only called from the collision event
// i have to deduce that its some sort of multicollision that is
// remembered and recalled

 

default
{
state_entry()
{
llSitTarget( < 0.0, 0.0, -0.1 >, ZERO_ROTATION ); // so someone can sit in the ball while its knocking down the pins.
llCollisionFilter("MYRTLE COVE BOWLING SET","",TRUE); // only if i hit pins
motionless = llGetPos(); // where am i now?
llSetTimerEvent(1800); // if i'm still there 30 minutes from now ...

}

 

collision_start(integer numberOfCollisions) // hit some pins
{
llSetTimerEvent(0); // stop the death timer
llSleep(10); // wait for the colliding to have its full chance
ballReturn(); // return the ball close to the start poin
motionless = llGetPos(); // where am i now?
llSetTimerEvent(1800); // if i'm still there 30 minutes from now ...

}


timer() // if i'm not colliding with pins, but still being played with, i'm safe
{
if (motionless == llGetPos()) // have i not been used in 30 minutes?
{
llDie(); // keep the sim clean
}

llSetTimerEvent(1800); // if i'm still there 30 minutes from now ...

}

}

 

 

Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

You're misinterpreting the variable that you have called Number of Collisions. That isn't a variable that you can "set".  It is the cumber of collisions that the script detects.  Normally, a collision_start event will only report a single collision, so scripters are justified in simply looking at that one ( as in llDetectedKey(0) or llDetectedPos(0) ).  If your object collides with several objects in a very short time, though, it wil report collisions with each of them.  If you only want to pay attention to one of them, tell the script to stop responding after the first collision triggers it. One very easy way to do that is something like this.

 

collision_start(integer num){    if (!gHit)   // Where gHit is a global integer variable    {        llOwnerSay("I was just hit by " + llDetectedName(0));        gHit = TRUE;        llSetTimerEvent(2.0);  // Or some convenient time later    }}timer(){    gHit = FALSE;    llSetTimerEvent(0.0);}

When you do something like that, your script will only respond to that one first hit and will ignore any others for the next 2 seconds.

In your particular case, you are already running a timer for another purpose, so you're going to have to either multiplex that timer to let it do more than one thing or run a second, fake timer.  I recommend multiplexing in this case.  Run it as a two-second timer.  Use llResetTime when you start the timer and then use

 

timer(){    if (llGetTime() > 2.0)    {        gHit = FALSE;    }    else if (llGetTime() > 1800.0)    {        llDie();    }}

Incidentally, I would also recommend not using llSleep unless absolutely necessary.  That function does exactly what it says.  It tells the script to stop paying attention to anything at all -- all communication, touch, collision, link messages,... everything will be ignored during the sleep period.  Occasionally that's exactly what you want, but it's a bad habit to get into using llSleep when you really mean "Wait until x seconds from now".  That's what we have timer events for.

 ETA:  And yes, Alwin is correct. A question like this really belongs in the LSL Scripting forum.  :smileywink:

  • Like 1
Link to comment
Share on other sites

  • 0

I'll expand on Rolig's advice (and concur with Alwin ;-).

Because the collision detector may fire in rapid succession upon hitting pins, you either need to disable collision detection for some time, or insert some gating event that must happen before collisions are accepted again. The ballReturn() function could check Rolig's "gHit" variable, and if it's set, do nothing. That variable can be reset by a timer, or some other thing that must happen in-game before another collision is accepted.

And you can greatly expand on the capabilities of the timer event by having it fire at some regular interval and manage any number of sub timers. Here's an untested example of a potential timer event handler...

tick = 10; // number of seconds per timer event.
// Pick something evenly divisible into a minute
// and the coarsest granularity you need in your game to minimize script time

minutes = 60/tick; // a convenient way to specify minutes

// Set up as many timers as neededinteger timer1duration = 1 * minutes; // a convenient way to specify timer durationinteger gTimer1;

integer timer2duration = 3.5*minutes;
integer gTimer2;
integer timer3duration = 30* minutes;
integer gTimer3;

// enable the timer event handler to manipulate all those timers
llSetTimerEvent(tick);
timer(){ if(gTimer1){ gTimer1--; } else { // insert whatever must be done when timer1 expires
// including restarting the timer with "gTimer1 = timer1duration;" }
if(gTimer2){ gTimer2--;
} else{ // insert whatever must be done when timer2 expires
// including restarting the timer with "gTimer2 = timer2duration;" }
if(gTimer3){ gTimer3--;
} else{ // insert whatever must be done when timer3 expires
// including restarting the timer with "gTimer3 = timer3duration;" }) // end of timer event

If you want a timer to cycle constantly, you'd restart it within the else{} portion of the timer. You can also start a timer by placing the initialization statement "gTimerX = timerXduration;" anywhere else in the script, much as you'd do with llSetTimerEvent(); Setting a timerX variable to zero will disable that timer unless it has been set to cycle constantly by reloading duration in the else{} block. You can expand the logic of the sub timers to provide both auto recycling and external (to the event) enable/disable by adding another global variable (per timer) that either controls decrementing of the timer, or reloading of it.

Good luck!

 

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3163 days.

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
 Share

×
×
  • Create New...