Jump to content

[Making a creature wander about]Character will not navigate not ignoring phantom mesh and not navigating through it. llWanderWithin failure


VirtualKitten
 Share

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

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

Recommended Posts

I have a horse animesh that is super but it wont navigate and follow me through Phantom mesh grass . Is there something I am missing please ?

I am sure this must have come up before ?

27edfb60c62fd7616ef36bbb56886313.jpg

This is just the basic wiki.secondlife.com  code 


float MIN_SCARE_RANGE = .015;
float SENSE_DISTANCE = MIN_SCARE_RANGE;
vector WANDER_RANGE = <15.0,15.0,5.0>;
vector CURIOUS_RANGE = <10.0,10.0,5.0>;

// The radius of the "capsule" Pathfinding thinks is around your character.
float CHARACTER_CAPSULE_RADIUS = 1;
float CHARACTER_CAPSULE_LENGTH = .46;
// If your character is considerably longer than wide, consider using CHARACTER_RADUIS and CHARACTER_LENGTH

integer minSecBetweenAttacks = 60; // I should take a break betweek attacks so I'm not quite so annoying.
string VICTIM_WEARABLE = "blah"; // Avatars wear this so I know I can attack them.

string walkanimation = "ANIM_HorseWalk";
string idleanimation = "ANIM_HorseEating";
string attackanimation = "ANIM_HorseIdle1";

vector my_home; // The center of my world.
key Current_Terror = NULL_KEY; // fearsome avatar
key Current_Curiosity = NULL_KEY; // The avatar I'm curious about

// I don't use SensorRepeat because only the most recent sensor event is queued. Previous sensor events are replaced. 
float TICK = 0.25; // seconds before next check
integer sensor_waiting; // flag

integer flagIsIdle = TRUE; // Am I idling or walking?

key Current_Victim = NULL_KEY; // avatar I want to attack
integer lastattacktime = 0; // tracking when I last attacked

float post_jump_sec = 0.5; // time to wait after I jump
float post_attack_sec = 1.5; // time to wait after I attack

float pursue_dist = 1.75;

integer useDebug = TRUE; // debug chatter? or no?
string debugObjDesc = "DEBUG";

Debug( string s )
{
    if ( useDebug == FALSE ) return;
    
    llSetText( s, <1,1,1>, 1.0 );
    //llOwnerSay( s );
    //llShout( s );
}

CreateCalmChar()
{
    llCreateCharacter([ CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL, CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH, CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS, CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

CreateFastChar()
{
    llCreateCharacter([CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL,  CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH,CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS, CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

ShowFear( integer bool )
{   
    // jump!
    if ( bool == TRUE )
    {
        llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
        llSleep( post_jump_sec );
    }
}

vector GetAvRegionPos( key av )
{
    list l = llGetObjectDetails( av, [ OBJECT_POS ] );
    return ( llList2Vector( l, 0 ) );
}

integer IsPotentialVictim( key av )  // Is that avatar wearing the VICTIM_WEARABLE?
{
    if ( lastattacktime + minSecBetweenAttacks < llGetUnixTime() ) 
    {
        list attachedUUIDs = llGetAttachedList(av);
        list objdetails;
        integer i  = llGetListLength( attachedUUIDs ) -1;
        for ( ; i > -1; --i )
        {
            objdetails = llGetObjectDetails(llList2Key(attachedUUIDs,i),[OBJECT_NAME]);
            if ( llList2String(objdetails,0) == VICTIM_WEARABLE )
            {
                return TRUE;
            }
        }
    }
    
    return FALSE;
}

DoWhileCurious()
{
   // if ( Current_Curiosity == NULL_KEY ) return;
    //list points = [llGetPos() + <5,0,0>, llGetPos() - <5,0,0>];
      //  llPatrolPoints(points, [PATROL_PAUSE_AT_WAYPOINTS, TRUE]);
    CreateCalmChar();
    llWanderWithin( llList2Vector( llGetObjectDetails( Current_Curiosity, [OBJECT_POS]), 0 ), CURIOUS_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
    Debug("O.O" );
}

SwitchToFleeing( key av )
{
    Current_Terror = av;
    Current_Curiosity = NULL_KEY;
    Current_Victim = NULL_KEY;
                    
    CreateFastChar();
    llEvade( av, [] );
    llStopLookAt();
    
    llSetTimerEvent( TICK );
}

DoAttack()
{
    if ( Current_Victim == NULL_KEY ) return;
    
    llStartObjectAnimation( attackanimation );
    llStopObjectAnimation( walkanimation );
    llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
    llTriggerSound( "SFX_horseSnort1", 1.0 );
    llSleep( post_attack_sec );
    llStartObjectAnimation( walkanimation );
    llStopObjectAnimation( attackanimation );
    
    lastattacktime = llGetUnixTime();
    
    SwitchToFleeing( Current_Victim );
}

DoSomething( key av )
{
    if ( av == NULL_KEY ) // wander around or stand and idle
    {
        llStopLookAt();
        if( (integer)llFrand( 25.0 ) == 0 )
        {
            if ( flagIsIdle == FALSE )
            {
                Debug("Standing...");
                llSetTimerEvent( 3.0 );
                llExecCharacterCmd( CHARACTER_CMD_STOP, [] );
                llStartObjectAnimation( idleanimation );
                llStopObjectAnimation( walkanimation );
                flagIsIdle = TRUE;
            }
        }
        else
        {
            if ( flagIsIdle == TRUE )
            {
                Debug("Wandering...");
                llStartObjectAnimation( walkanimation );
                llStopObjectAnimation( idleanimation );
                flagIsIdle = FALSE;
                llWanderWithin( my_home, WANDER_RANGE, []);
            }
        }
        
        if ( Current_Terror == NULL_KEY && Current_Curiosity == NULL_KEY ) return;
            
        CreateCalmChar();
        
        Current_Terror = NULL_KEY;
        Current_Curiosity = NULL_KEY;
        Current_Victim = NULL_KEY;

        ShowFear( FALSE );
    }
    else // I have someone!
    {
        llStartObjectAnimation( walkanimation );
        llStopObjectAnimation( idleanimation );
            
        integer agentinfo = llGetAgentInfo(av);

        if ( agentinfo & AGENT_AWAY ) // If the av is away... pace around them
        {     
            if ( av == Current_Curiosity ) return;
                
            Debug("Curious...");
            
            Current_Curiosity = av;
            Current_Terror = NULL_KEY;
            Current_Victim = NULL_KEY;
            
            CreateCalmChar();
            llPursue( av, [PURSUIT_GOAL_TOLERANCE, pursue_dist] ); // Come right up
            ShowFear( FALSE );
        }
        else // flee or attack!
        {
            if ( av == Current_Terror ) return; // if I'm fleeing them, keep fleeing.
            if ( av == Current_Victim ) return; // if I'm attacking, keep attacking.
        
            if ( Current_Terror == NULL_KEY && Current_Victim == NULL_KEY ) // decide if I'm attacking or fleeing
            {
                if ( IsPotentialVictim(av) == TRUE )
                {
                    Debug("Attacking...");
                
                    Current_Terror = NULL_KEY;
                    Current_Curiosity = NULL_KEY;
                    Current_Victim = av;
                    
                    CreateFastChar();
                    llPursue( av, [ PURSUIT_INTERCEPT, TRUE, PURSUIT_GOAL_TOLERANCE, pursue_dist ] );
                    
                    llLookAt( GetAvRegionPos(av), 0.01, 0.2 );
                }
                else
                {
                    llStopLookAt();
                    ShowFear( TRUE );
                    // start fleeing
                    SwitchToFleeing( av );
                    
                }
            }   
        }
    }
}

default
{
    state_entry()
    {
        llSetText( "", <1,1,1>, 0.0 );
        useDebug = FALSE;
        if( llGetObjectDesc() == debugObjDesc )
        {
            useDebug = TRUE;
        }
        
        llDeleteCharacter(); // always start with this - clears the object.
        CreateCalmChar();
        
        my_home = llGetPos();
        llWanderWithin( my_home, WANDER_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
        Debug("Wandering...");
        
        ShowFear( FALSE );
        llCollisionSound( "", 0.0 );
        
        sensor_waiting = FALSE;
        llSetTimerEvent( TICK );
        
        llStartObjectAnimation( walkanimation );
        flagIsIdle = FALSE;
    }
    
    timer()
    {
        llSetTimerEvent( 0.0 );
        
        // The script can only have one sensor event queued at a time.
        // If we add a second, the first one never gets processed.
        if ( sensor_waiting == FALSE )
        {
            llSensor( "", NULL_KEY, AGENT, SENSE_DISTANCE, PI );
            sensor_waiting == TRUE;
        }
        
        llSetTimerEvent( TICK );
    }
    
    sensor( integer n )
    {
        sensor_waiting = FALSE;
        
        float closest_av_dist = MIN_SCARE_RANGE;
        key closest_av = NULL_KEY;
        
        integer x = 0;
        vector pos;
        key av;
        float dist;
        
        for ( ; x < n; ++x )
        {
            av = llDetectedKey(x);
            pos = llDetectedPos(x);
            dist = llVecDist( llGetPos(), pos );
            
            
            if ( dist < MIN_SCARE_RANGE )
            {
                if ( dist < closest_av_dist )
                {
                    closest_av = av;
                    closest_av_dist = dist;
                }
            }
        }

        DoSomething(closest_av);
    }
    
    no_sensor()
    {
        sensor_waiting = FALSE;
        DoSomething(NULL_KEY);
    }

    
    touch_start(integer total_number)
    {
        if ( llDetectedKey(0) == llGetOwner() )
        {
            llSetTimerEvent( 0.0 );
            Debug("Stopping. Reset my script to start me again.");
            
            list temp = llGetObjectAnimationNames();
            integer n = llGetListLength( temp );
            for ( --n; n > -1; --n )
            {
                llStopObjectAnimation( llList2String(temp,n) );
            }
            
            llDeleteCharacter(); // Revert back to a normal prim on touch
        }
    }
    
    path_update(integer type, list reserved)
    {
        if (type == 0)
        {
            Debug("Near");
        }
        else if (type == 1)
        {
            //Debug("Stopping"); 
            DoWhileCurious();
            DoAttack();
        }
        else if (type == 2)
        {
            Debug("Cannot path find from current location!");
        }
        else if (type == 3)
        {
            Debug("Goal not on navmesh!");
        }
        else if (type == 4)
        {
            Debug("Goal unreachable!");
            // I freeze when this happens. So...
            DoSomething( NULL_KEY );
        }
        else if (type == 5)
        {
            Debug("Target gone!");
        }
        else if (type == 6)
        {
            Debug("No place to go!");
            // I freeze when this happens. So...
            DoSomething( NULL_KEY );
        }
        else if (type == 7)
        {
            Debug("Hiding from pursuer...");
        }
        else if (type == 8)
        {
            Debug("Switched from hiding to running...");
        }
        else if (type == 9)
        {
            Debug("Region has no nav mesh..");
        }
        else if (type == 10)
        {
            Debug("Dynamic pathfinding is disabled in this region.");
        }
        else if (type == 11)
        {
            Debug("Parcel entry problem (is the parcel full?).");
        }
        else if (type == 1000000)
        {
            Debug("Hit an unspecified failure");
        }
        else
        {
            Debug("Unknown failure");
        }
    }
    
}

D

Edited by VirtualKitten
Added added topic key
Link to comment
Share on other sites

  • VirtualKitten changed the title to Character will not navigate not ignoring phantom mesh and not navigating through it.

It's hard to tell from that what the problem is. If you have some terrain of your own on top of Linden ground, it has to be set as "Walkable" in Build->Pathfinding.

Few people know how to set up SL pathfinding properly, which is why I don't sell my NPCs. Takes too much support effort. Documentation is terrible. Two little known facts: 1) if you set "Static obstacle" or "Walkable" for a linkset, all moving parts of the linkset are frozen in place. Including doors. 2) "Walkable" means "Walkable if up to 60 degree slope, then static obstacle", which is very convenient. I have a JIRA in on #1; it's been accepted, but, of course, not fixed.

Anyway. I have two tools which can help with setup, "Come Here" and "Amulet of Pathfinding". These are both on Marketplace, cheap.

"Come Here" is just a prim set up for pathfinding. You rez it, click on it, and it tries to come to you, displaying any errors. If Come Here won't move, work on the pathfinding properties of the surface underneath.

"Amulet of Pathfinding" is a wearable amulet for examining pathfinding properties of objects. Worn on the left wrist. Click on it to turn it on; it glows when on, like any self-respecting magic item. Then go into mouselook and click on ground locations. It does an LLCast Ray and reports the objects hit by the ray and their pathfinding status. It ends with "CAN walk here" or "CANNOT walk here". This is useful when setting up pathfinding.

In general, SL pathfinding only works well when you have a lot of open space, the pathfinding object moves slowly, and the sim isn't overloaded. Outdoor grazing animals, yes; waitress in crowded club, no.

Link to comment
Share on other sites

Animats The llWanderWithin is not doing that at all. I must be missing something , Oh  its on a sky platform . Oh lord why does linden make this so complicated so it has to be set up on the whole SiM? How is this achieved?

 

Edited by VirtualKitten
message came in while I was posting
Link to comment
Share on other sites

@Animats,

Is there anyway I can do path-finding my self  instead of relying on the LSL restricted lands setting versions.  presumably need a wander collision code  set of in certain direction ?

I am sure this used to be done before as usual wiki.secondlife.com has nothing about this on their pages just inferring it works when you use it . My understanding of pathfinding is away to navigate between two points avoiding obstacles . How is wandering about ?

 

Your item reported [10:33] Come Here Fast v0.04: Failed to reach goal. Path update status: Target (for llPursue or llEvade) can no longer be tracked - e.g., it left the region or is an avatar that is now more than about 30m outside the region

 

Also if its broken how does my kittycats mange to follow me?

Edited by VirtualKitten
Link to comment
Share on other sites

Will NavigateTo() report the same kind of errors too. Why is this problem not helpfully  stated on wiki.secondlife.com @animats ,  cricky if it was and how to solve it it would be so much easier 

I am guessing after easing numerous threads on animals walking about I am walking about my room going nutty  as your lovely item said Your item reported [10:33] Come Here Fast v0.04: Failed to reach goal. Path update status: Target (for llPursue or llEvade) can no longer be tracked - e.g., it left the region or is an avatar that is now more than about 30m outside the region I presume something is not configured and need to inform my land owner how to fix this can anyone explain what needs to be fixed to get path finding working on our sim pleas?

Edited by VirtualKitten
Link to comment
Share on other sites

  • VirtualKitten changed the title to [Making a creature wander about]Character will not navigate not ignoring phantom mesh and not navigating through it. llWanderWithin failure
2 hours ago, VirtualKitten said:

Oh  its on a sky platform

Is the platform surface marked as walkable. By default, Linden ground is walkable, but nothing you create is walkable by default.

Quote

The wiki says there is a "pathfinding disabled" icon

If pathfinding is disabled (rarely seen on mainland) an icon with a squggle superimposed a red "do not enter" symbol wlll appear on the top toolbar.

Link to comment
Share on other sites

Hi Kyhrah , Oh thank you for your relies everyone.  I traveled to a magical place yesterday in second life  Animats Cafe and Vehicle  R&D meeting some friendly people who live there after much bewilderment my horse ran free and wandered about gracefully all around us it was truly magical and breath taking the man part of a lovely family there was very  much a wizard knowing more secrets about second life than I had dared to look at under plain site. The pathfinding menus are all there Build  Menu  >> Path finding  >> Region Objects . I learned about required area sizes 10m x 10m and was able to create a flat prim 10x10 right click it to get pie menu and press 'more' twice'  until the pathfinding menu appeared and could be selected this entered the same screen as the Build Menu >> Build Objects >> Region Objects  Pathfinding window but with the flat plane I selected selected in the window. He told me I could make this walkable by changing the setting at the bottom of this screen to 'Walkable' and noting two applies press the bottom one at the bottom of the screen to 'Apply Changes'  (pictured below) the walkable pathfinding. This created a walkable prim on top of the Mega prim. I then had to look up on the SURL to see the 'squiggle menu'  that had appeared there . Pressing this he said  Built the model in second life rendering it in the world. Although this tested with his amulet as walkable land  our attempts  to create and area the same as the Animats Cafe and Vehicle  R&D failed I am hopeful I will find him again and we will find out what's wrong with what we had tried so far . The Mega Mesh Prim we had tried this on Kyhrah was owned but another avatar that I had permissions to modify   but I could not get permission from 'squiggle' menu to re render and map this in the region. It must require a different permission. I can thank everyone enough for their help.


The land or prim must show with pathfinding like it does at bottom of screen:

96dff5a8310f91597651d805f37dfcf9.png

Were it says Pathfinding attributes : Affects navmesh  it can also say character. I don't know what this means currently.  I have a feeling this difference is the reason its not working as it does on the other sim?

The bottom of the Region Objects Screen to set the object build 

ac23bd419795bc077374dee5fa393aae.png

I even went back to check I had not imagined the horse running about .  I note on the mega prim we have we get an error [01:26] Come Here Fast v0.04: Pursue.
[01:26] Come Here Fast v0.04: Pathfinding started.
[01:26] Come Here Fast v0.04: Failed to reach goal. Path update status: Target (for llPursue or llEvade) can no longer be tracked - e.g., it left the region or is an avatar that is now more than about 30m outside the region.
D.

Edited by VirtualKitten
Link to comment
Share on other sites

Yes it rebaked  there is not squiggle visible on a mega prim at present  for test purposes it returns a PU FAILURE TARGET GONE the ground is now walkable 

 

If i put the test code for errors in my horse 

I get  There's no good place for the character to go - e.g., it is patrolling and all the patrol points are now unreachable. ie PU_FAILURE_NO_VALID_DESTINATION

 

Edited by VirtualKitten
NA
Link to comment
Share on other sites

Have now shortened my code slightly 
 


float MIN_SCARE_RANGE = .5;
float SENSE_DISTANCE = MIN_SCARE_RANGE;
vector WANDER_RANGE = <11.0,11.0,5.0>;
vector CURIOUS_RANGE = <10.0,10.0,5.0>;

// The radius of the "capsule" Pathfinding thinks is around your character.
float CHARACTER_CAPSULE_RADIUS = 1.62;
float CHARACTER_CAPSULE_LENGTH = 3.3;
integer Character_Type =CHARACTER_TYPE_D;
float Character_Turning_Speed=3;
float Character_Turning_Radius=2.5;
// If your character is considerably longer than wide, consider using CHARACTER_RADUIS and CHARACTER_LENGTH

integer minSecBetweenAttacks = 60; // I should take a break betweek attacks so I'm not quite so annoying.
string VICTIM_WEARABLE = "blah"; // Avatars wear this so I know I can attack them.

string walkanimation = "ANIM_HorseWalk";
string idleanimation = "ANIM_HorseEating";
string attackanimation = "ANIM_HorseWalkBack";

vector my_home; // The center of my world.
key Current_Terror = NULL_KEY; // fearsome avatar
key Current_Curiosity = NULL_KEY; // The avatar I'm curious about

// I don't use SensorRepeat because only the most recent sensor event is queued. Previous sensor events are replaced. 
float TICK = 0.25; // seconds before next check
integer sensor_waiting; // flag

integer flagIsIdle = TRUE; // Am I idling or walking?

key Current_Victim = NULL_KEY; // avatar I want to attack
integer lastattacktime = 0; // tracking when I last attacked

float post_jump_sec = 0.5; // time to wait after I jump
float post_attack_sec = 1.5; // time to wait after I attack

float pursue_dist = 1.75;

integer useDebug = TRUE; // debug chatter? or no?
string debugObjDesc = "DEBUG";

Debug( string s )
{
    if ( useDebug == FALSE ) return;
    
    llSetText( s, <1,1,1>, 1.0 );
    //llOwnerSay( s );
    //llShout( s );
}

CreateCalmChar()
{
    llCreateCharacter([ CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL, CHARACTER_TYPE,Character_Type, CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH,CHARACTER_DESIRED_TURN_SPEED,Character_Turning_Speed, CHARACTER_MAX_TURN_RADIUS,Character_Turning_Radius,CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS,  CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

CreateFastChar()
{
    llCreateCharacter([CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL,   CHARACTER_TYPE,Character_Type,CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH,CHARACTER_DESIRED_TURN_SPEED,Character_Turning_Speed,CHARACTER_MAX_TURN_RADIUS,Character_Turning_Radius,CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS, CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

ShowFear( integer bool )
{   
    // jump!
    if ( bool == TRUE )
    {
         llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
         llStartObjectAnimation( walkanimation );
         llStopObjectAnimation( attackanimation );
        llSleep( post_jump_sec );
    }
}
string path_err_msg(integer patherr)
{   list patherrs =[
    "Character is near current goal.",
    "Character has reached the goal.",
    "Character cannot navigate from the current location - e.g., the character is off the navmesh or too high above it.",
    "Goal is not on the navmesh and cannot be reached.",
    "Goal is no longer reachable for some reason - e.g., an obstacle blocks the path.",
    "Target (for llPursue or llEvade) can no longer be tracked - e.g., it left the region or is an avatar that is now more than about 30m outside the region.",
    "There's no good place for the character to go - e.g., it is patrolling and all the patrol points are now unreachable.",
    "An llEvade character thinks it has hidden from its pursuer.",
    "An llEvade character switches from hiding to running",
    "A fatal error reported to a character when there is no navmesh for the region. This usually indicates a server failure and users should file a bug report and include the time and region in which they received this message.",
    "Character entered a region with dynamic pathfinding disabled.",
    "A character failed to enter a parcel because it is not allowed to enter, e.g. because the parcel is already full or because object entry was disabled after the navmesh was baked."];
    if (patherr < llGetListLength(patherrs))
    {   return(llList2String(patherrs,patherr));
    } else {
        return("Unknown path error " + (string) patherr);
    }
}
vector GetAvRegionPos( key av )
{
    list l = llGetObjectDetails( av, [ OBJECT_POS ] );
    return ( llList2Vector( l, 0 ) );
}

integer IsPotentialVictim( key av )  // Is that avatar wearing the VICTIM_WEARABLE?
{
    if ( lastattacktime + minSecBetweenAttacks < llGetUnixTime() ) 
    {
        list attachedUUIDs = llGetAttachedList(av);
        list objdetails;
        integer i  = llGetListLength( attachedUUIDs ) -1;
        for ( ; i > -1; --i )
        {
            objdetails = llGetObjectDetails(llList2Key(attachedUUIDs,i),[OBJECT_NAME]);
            if ( llList2String(objdetails,0) == VICTIM_WEARABLE )
            {
                return TRUE;
            }
        }
    }
    
    return FALSE;
}

DoWhileCurious()
{
   if ( Current_Curiosity == NULL_KEY ) return;
    //list points = [llGetPos() + <5,0,0>, llGetPos() - <5,0,0>];
      //  llPatrolPoints(points, [PATROL_PAUSE_AT_WAYPOINTS, TRUE]);
    CreateCalmChar();
    llWanderWithin( llList2Vector( llGetObjectDetails( Current_Curiosity, [OBJECT_POS]), 0 ), CURIOUS_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
    Debug("O.O" );
}

SwitchToFleeing( key av )
{
    Current_Terror = av;
    Current_Curiosity = NULL_KEY;
    Current_Victim = NULL_KEY;
                    
    CreateFastChar();
    llEvade( av, [] );
    llStopLookAt();
    
    llSetTimerEvent( TICK );
}

DoAttack()
{
    if ( Current_Victim == NULL_KEY ) return;
    
    llStartObjectAnimation( attackanimation );
    llStopObjectAnimation( walkanimation );
    llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
    llTriggerSound( "SFX_horseSnort1", 1.0 );
    llSleep( post_attack_sec );
    llStartObjectAnimation( walkanimation );
    llStopObjectAnimation( attackanimation );
    
    lastattacktime = llGetUnixTime();
    
    SwitchToFleeing( Current_Victim );
}

DoSomething( key av )
{
    if ( av == NULL_KEY ) // wander around or stand and idle
    {
        llStopLookAt();
        if( (integer)llFrand( 25.0 ) == 0 )
        {
            if ( flagIsIdle == FALSE )
            {
                Debug("Standing...");
                llSetTimerEvent( 3.0 );
                llExecCharacterCmd( CHARACTER_CMD_STOP, [] );
                llStartObjectAnimation( idleanimation );
                llStopObjectAnimation( walkanimation );
                flagIsIdle = TRUE;
            }
        }
        else
        {
            if ( flagIsIdle == TRUE )
            {
                Debug("Wandering...");
                llStartObjectAnimation( walkanimation );
                llStopObjectAnimation( idleanimation );
                flagIsIdle = FALSE;
                llWanderWithin( my_home, WANDER_RANGE, []);
            }
        }
        
        if ( Current_Terror == NULL_KEY && Current_Curiosity == NULL_KEY ) return;
            
        CreateCalmChar();
        
        Current_Terror = NULL_KEY;
        Current_Curiosity = NULL_KEY;
        Current_Victim = NULL_KEY;

        ShowFear( FALSE );
    }
    else // I have someone!
    {
        llStartObjectAnimation( walkanimation );
        llStopObjectAnimation( idleanimation );
            
        integer agentinfo = llGetAgentInfo(av);

        if ( agentinfo & AGENT_AWAY ) // If the av is away... pace around them
        {     
            if ( av == Current_Curiosity ) return;
                
            Debug("Curious...");
            
            Current_Curiosity = av;
            Current_Terror = NULL_KEY;
            Current_Victim = NULL_KEY;
            
            CreateCalmChar();
            llPursue( av, [PURSUIT_GOAL_TOLERANCE, pursue_dist] ); // Come right up
            ShowFear( FALSE );
        }
        else // flee or attack!
        {
            if ( av == Current_Terror ) return; // if I'm fleeing them, keep fleeing.
            if ( av == Current_Victim ) return; // if I'm attacking, keep attacking.
        
            if ( Current_Terror == NULL_KEY && Current_Victim == NULL_KEY ) // decide if I'm attacking or fleeing
            {
                if ( IsPotentialVictim(av) == TRUE )
                {
                    Debug("Attacking...");
                
                    Current_Terror = NULL_KEY;
                    Current_Curiosity = NULL_KEY;
                    Current_Victim = av;
                    
                    CreateFastChar();
                    llPursue( av, [ PURSUIT_INTERCEPT, TRUE, PURSUIT_GOAL_TOLERANCE, pursue_dist ] );
                    
                    llLookAt( GetAvRegionPos(av), 0.01, 0.2 );
                }
                else
                {
                    llStopLookAt();
                    ShowFear( TRUE );
                    // start fleeing
                    SwitchToFleeing( av );
                    
                }
            }   
        }
    }
}

default
{
    state_entry()
    {
        llSetText( "", <1,1,1>, 0.0 );
        useDebug = FALSE;
        if( llGetObjectDesc() == debugObjDesc )
        {
            useDebug = TRUE;
        }
        
        llDeleteCharacter(); // always start with this - clears the object.
        CreateCalmChar();
        
        my_home = llGetPos();
        llWanderWithin( my_home, WANDER_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
        Debug("Wandering...");
        
        ShowFear( FALSE );
        llCollisionSound( "", 0.0 );
        
        sensor_waiting = FALSE;
        llSetTimerEvent( TICK );
        
        llStartObjectAnimation( walkanimation );
        flagIsIdle = FALSE;
    }
    
    timer()
    {
        llSetTimerEvent( 0.0 );
        
        // The script can only have one sensor event queued at a time.
        // If we add a second, the first one never gets processed.
        if ( sensor_waiting == FALSE )
        {
            llSensor( "", NULL_KEY, AGENT, SENSE_DISTANCE, PI );
            sensor_waiting == TRUE;
        }
        
        llSetTimerEvent( TICK );
    }
    
    sensor( integer n )
    {
        sensor_waiting = FALSE;
        
        float closest_av_dist = MIN_SCARE_RANGE;
        key closest_av = NULL_KEY;
        
        integer x = 0;
        vector pos;
        key av;
        float dist;
        
        for ( ; x < n; ++x )
        {
            av = llDetectedKey(x);
            pos = llDetectedPos(x);
            dist = llVecDist( llGetPos(), pos );
            
            
            if ( dist < MIN_SCARE_RANGE )
            {
                if ( dist < closest_av_dist )
                {
                    closest_av = av;
                    closest_av_dist = dist;
                }
            }
        }

        DoSomething(closest_av);
    }
    
    no_sensor()
    {
        sensor_waiting = FALSE;
        DoSomething(NULL_KEY);
    }

    
    touch_start(integer total_number)
    {
        if ( llDetectedKey(0) == llGetOwner() )
        {
            llSetTimerEvent( 0.0 );
            Debug("Stopping. Reset my script to start me again.");
            
            list temp = llGetObjectAnimationNames();
            integer n = llGetListLength( temp );
            for ( --n; n > -1; --n )
            {
                llStopObjectAnimation( llList2String(temp,n) );
            }
            
            llDeleteCharacter(); // Revert back to a normal prim on touch
        }
    }
    path_update(integer type, list reserved) {
        if (type == PU_FAILURE_UNREACHABLE
        || type == PU_FAILURE_INVALID_GOAL
        || type == PU_FAILURE_INVALID_START
        || type == PU_FAILURE_TARGET_GONE
        || type == PU_FAILURE_NO_VALID_DESTINATION
        || type == PU_FAILURE_NO_NAVMESH)
        {   llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
            llOwnerSay("Failed to reach goal. Path update status: " + path_err_msg(type));
            return;
        }
        if (type == PU_GOAL_REACHED)
        {   llOwnerSay("Reached goal.");
            llExecCharacterCmd(CHARACTER_CMD_STOP, []);
            return;
        }
       llOwnerSay("Other path update:  " + path_err_msg(type));
        
       
    }
    
}

 

Link to comment
Share on other sites

I have also tried adding in patrol points 

 

DoWhileCurious()
{
   if ( Current_Curiosity == NULL_KEY ) return;
    list points = [llGetPos() + <10,0,0>, llGetPos() - <10,0,0>];
    llPatrolPoints(points, [PATROL_PAUSE_AT_WAYPOINTS, TRUE]);
    CreateCalmChar();
    llWanderWithin( llList2Vector( llGetObjectDetails( Current_Curiosity, [OBJECT_POS]), 0 ), CURIOUS_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
    Debug("O.O" );
}

Link to comment
Share on other sites

oh IT seems it was something i Deleted but still didn't resolve it moving and stopping it reporting this error here's no good place for the character to go - e.g., it is patrolling and all the patrol points are now unreachable. ie PU_FAILURE_NO_VALID_DESTINATION

 

    path_update(integer type, list reserved) {
        if (type == 0) Debug("Near");
        else if(type == 1) {
            //Debug("Stopping");
            DoWhileCurious();
            DoAttack();
        }
       
        if (type == PU_FAILURE_UNREACHABLE
        || type == PU_FAILURE_INVALID_GOAL
        || type == PU_FAILURE_INVALID_START
        || type == PU_FAILURE_TARGET_GONE
        || type == PU_FAILURE_NO_VALID_DESTINATION
        || type == PU_FAILURE_NO_NAVMESH)
        {   llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
            llOwnerSay("Failed to reach goal. Path update status: " + path_err_msg(type));
            return;
        }
        if (type == PU_GOAL_REACHED)
        {   llOwnerSay("Reached goal.");
            llExecCharacterCmd(CHARACTER_CMD_STOP, []);
            return;
        }
       llOwnerSay("Other path update:  " + path_err_msg(type));
        
       
    }

Edited by VirtualKitten
i forgot something
Link to comment
Share on other sites

I went to Kitten's skybox, which is around 3900m altitude. I could not get pathfinding to move anything, for even my little Come Here test object. Pathfinding does seem to be on for the region. Are there any known problems with pathfinding at high altitude?

  • Like 1
Link to comment
Share on other sites

@animats I have put in your error code and now get a slightly different error message that i get for your clever come to me device it seems to suggest that it has no places being returned from the pathfinding suggesting either script is not providing information to llWanderWin  properly or there is some other reason I am not aware of.

 

@Tuu Munz      Hi thanks for providing the images i was going to do that but you brilliantly saved me a job thankyou its is all baked  but is returning strange errors.

 

I had some success with a dragon momentry https://i.gyazo.com/86c63881f6806038ce3fc29ededfe657.mp4 but don't want to change dragon to the error processing  until I can understand what is failing unfortunately wiki.secondlife.com does still not have much information other than a verbose message about absolute failure.

Link to comment
Share on other sites

1 hour ago, animats said:

I went to Kitten's skybox, which is around 3900m altitude. I could not get pathfinding to move anything, for even my little Come Here test object. Pathfinding does seem to be on for the region. Are there any known problems with pathfinding at high altitude?

Yes @animatsit was lovely to meet you properly @animats. The mega prim is now installed with what we was trying to achieve pathfinding Affects Navamesh but it is at 3000m altitude or there-abouts  its a very beautiful sim and I am lucky and privileged to have a home there as its a beautiful sim below us Galadriel's Mirror lease feel free to check it out . 

Since using @animats error checking from his script i get some better identification of what's not working his lovely come item returns a different error fatal lie the one in my horse n Ow if there is a platform at ground level that has horses running about on it does this suggest something is wrong with my code  I am going back to your sim to try again shortly animats . I hope that's ok . It will eliminate my script error being a script problem 

Link to comment
Share on other sites

@animatsThis leads me to believe it is something in my script as your 'come to me' app works xD on your site surely i should get the same error as your 'come to me' app at my home? :
 

My code i might be at fault now :


float MIN_SCARE_RANGE = .5;
float SENSE_DISTANCE = MIN_SCARE_RANGE;
vector WANDER_RANGE = <11.0,11.0,5.0>;
vector CURIOUS_RANGE = <10.0,10.0,5.0>;

// The radius of the "capsule" Pathfinding thinks is around your character.
float CHARACTER_CAPSULE_RADIUS = 1.62;
float CHARACTER_CAPSULE_LENGTH = 3.3;
integer Character_Type =CHARACTER_TYPE_D;
float Character_Turning_Speed=3;
float Character_Turning_Radius=2.5;
// If your character is considerably longer than wide, consider using CHARACTER_RADUIS and CHARACTER_LENGTH

integer minSecBetweenAttacks = 60; // I should take a break betweek attacks so I'm not quite so annoying.
string VICTIM_WEARABLE = "blah"; // Avatars wear this so I know I can attack them.

string walkanimation = "ANIM_HorseWalk";
string idleanimation = "ANIM_HorseEating";
string attackanimation = "ANIM_HorseWalkBack";

vector my_home; // The center of my world.
key Current_Terror = NULL_KEY; // fearsome avatar
key Current_Curiosity = NULL_KEY; // The avatar I'm curious about

// I don't use SensorRepeat because only the most recent sensor event is queued. Previous sensor events are replaced. 
float TICK = 0.25; // seconds before next check
integer sensor_waiting; // flag

integer flagIsIdle = TRUE; // Am I idling or walking?

key Current_Victim = NULL_KEY; // avatar I want to attack
integer lastattacktime = 0; // tracking when I last attacked

float post_jump_sec = 0.5; // time to wait after I jump
float post_attack_sec = 1.5; // time to wait after I attack

float pursue_dist = 1.75;

integer useDebug = TRUE; // debug chatter? or no?
string debugObjDesc = "DEBUG";

Debug( string s )
{
    if ( useDebug == FALSE ) return;
    
    llSetText( s, <1,1,1>, 1.0 );
    //llOwnerSay( s );
    //llShout( s );
}

CreateCalmChar()
{
    llCreateCharacter([ CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL, CHARACTER_TYPE,Character_Type, CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH,CHARACTER_DESIRED_TURN_SPEED,Character_Turning_Speed, CHARACTER_MAX_TURN_RADIUS,Character_Turning_Radius,CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS,  CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

CreateFastChar()
{
    llCreateCharacter([CHARACTER_STAY_WITHIN_PARCEL, TRUE, CHARACTER_ORIENTATION, HORIZONTAL,   CHARACTER_TYPE,Character_Type,CHARACTER_LENGTH,CHARACTER_CAPSULE_LENGTH,CHARACTER_DESIRED_TURN_SPEED,Character_Turning_Speed,CHARACTER_MAX_TURN_RADIUS,Character_Turning_Radius,CHARACTER_RADIUS, CHARACTER_CAPSULE_RADIUS, CHARACTER_MAX_SPEED, 6.0, CHARACTER_DESIRED_SPEED, 2.8]);
}

ShowFear( integer bool )
{   
    // jump!
    if ( bool == TRUE )
    {
         llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
         llStartObjectAnimation( walkanimation );
         llStopObjectAnimation( attackanimation );
        llSleep( post_jump_sec );
    }
}
string path_err_msg(integer patherr)
{   list patherrs =[
    "Character is near current goal.",
    "Character has reached the goal.",
    "Character cannot navigate from the current location - e.g., the character is off the navmesh or too high above it.",
    "Goal is not on the navmesh and cannot be reached.",
    "Goal is no longer reachable for some reason - e.g., an obstacle blocks the path.",
    "Target (for llPursue or llEvade) can no longer be tracked - e.g., it left the region or is an avatar that is now more than about 30m outside the region.",
    "There's no good place for the character to go - e.g., it is patrolling and all the patrol points are now unreachable.",
    "An llEvade character thinks it has hidden from its pursuer.",
    "An llEvade character switches from hiding to running",
    "A fatal error reported to a character when there is no navmesh for the region. This usually indicates a server failure and users should file a bug report and include the time and region in which they received this message.",
    "Character entered a region with dynamic pathfinding disabled.",
    "A character failed to enter a parcel because it is not allowed to enter, e.g. because the parcel is already full or because object entry was disabled after the navmesh was baked."];
    if (patherr < llGetListLength(patherrs))
    {   return(llList2String(patherrs,patherr));
    } else {
        return("Unknown path error " + (string) patherr);
    }
}
vector GetAvRegionPos( key av )
{
    list l = llGetObjectDetails( av, [ OBJECT_POS ] );
    return ( llList2Vector( l, 0 ) );
}

integer IsPotentialVictim( key av )  // Is that avatar wearing the VICTIM_WEARABLE?
{
    if ( lastattacktime + minSecBetweenAttacks < llGetUnixTime() ) 
    {
        list attachedUUIDs = llGetAttachedList(av);
        list objdetails;
        integer i  = llGetListLength( attachedUUIDs ) -1;
        for ( ; i > -1; --i )
        {
            objdetails = llGetObjectDetails(llList2Key(attachedUUIDs,i),[OBJECT_NAME]);
            if ( llList2String(objdetails,0) == VICTIM_WEARABLE )
            {
                return TRUE;
            }
        }
    }
    
    return FALSE;
}

DoWhileCurious()
{
   if ( Current_Curiosity == NULL_KEY ) return;
    list points = [llGetPos() + <10,0,0>, llGetPos() - <10,0,0>];
    llPatrolPoints(points, [PATROL_PAUSE_AT_WAYPOINTS, TRUE]);
    CreateCalmChar();
    llWanderWithin( llList2Vector( llGetObjectDetails( Current_Curiosity, [OBJECT_POS]), 0 ), CURIOUS_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
    Debug("O.O" );
}

SwitchToFleeing( key av )
{
    Current_Terror = av;
    Current_Curiosity = NULL_KEY;
    Current_Victim = NULL_KEY;
                    
    CreateFastChar();
    llEvade( av, [] );
    llStopLookAt();
    
    llSetTimerEvent( TICK );
}

DoAttack()
{
    if ( Current_Victim == NULL_KEY ) return;
    
    llStartObjectAnimation( attackanimation );
    llStopObjectAnimation( walkanimation );
    //llExecCharacterCmd( CHARACTER_CMD_JUMP, [0.75] );
    llTriggerSound( "SFX_horseSnort1", 1.0 );
    llSleep( post_attack_sec );
    llStartObjectAnimation( walkanimation );
    llStopObjectAnimation( attackanimation );
    
    lastattacktime = llGetUnixTime();
    
    SwitchToFleeing( Current_Victim );
}

DoSomething( key av )
{
    if ( av == NULL_KEY ) // wander around or stand and idle
    {
        llStopLookAt();
        if( (integer)llFrand( 25.0 ) == 0 )
        {
            if ( flagIsIdle == FALSE )
            {
                Debug("Standing...");
                llSetTimerEvent( 3.0 );
                llExecCharacterCmd( CHARACTER_CMD_STOP, [] );
                llStartObjectAnimation( idleanimation );
                llStopObjectAnimation( walkanimation );
                flagIsIdle = TRUE;
            }
        }
        else
        {
            if ( flagIsIdle == TRUE )
            {
                Debug("Wandering...");
                llStartObjectAnimation( walkanimation );
                llStopObjectAnimation( idleanimation );
                flagIsIdle = FALSE;
                llWanderWithin( my_home, WANDER_RANGE, []);
            }
        }
        
        if ( Current_Terror == NULL_KEY && Current_Curiosity == NULL_KEY ) return;
            
        CreateCalmChar();
        
        Current_Terror = NULL_KEY;
        Current_Curiosity = NULL_KEY;
        Current_Victim = NULL_KEY;

        ShowFear( FALSE );
    }
    else // I have someone!
    {
        llStartObjectAnimation( walkanimation );
        llStopObjectAnimation( idleanimation );
            
        integer agentinfo = llGetAgentInfo(av);

        if ( agentinfo & AGENT_AWAY ) // If the av is away... pace around them
        {     
            if ( av == Current_Curiosity ) return;
                
            Debug("Curious...");
            
            Current_Curiosity = av;
            Current_Terror = NULL_KEY;
            Current_Victim = NULL_KEY;
            
            CreateCalmChar();
            llPursue( av, [PURSUIT_GOAL_TOLERANCE, pursue_dist] ); // Come right up
            ShowFear( FALSE );
        }
        else // flee or attack!
        {
            if ( av == Current_Terror ) return; // if I'm fleeing them, keep fleeing.
            if ( av == Current_Victim ) return; // if I'm attacking, keep attacking.
        
            if ( Current_Terror == NULL_KEY && Current_Victim == NULL_KEY ) // decide if I'm attacking or fleeing
            {
                if ( IsPotentialVictim(av) == TRUE )
                {
                    Debug("Attacking...");
                
                    Current_Terror = NULL_KEY;
                    Current_Curiosity = NULL_KEY;
                    Current_Victim = av;
                    
                    CreateFastChar();
                    llPursue( av, [ PURSUIT_INTERCEPT, TRUE, PURSUIT_GOAL_TOLERANCE, pursue_dist ] );
                    
                    llLookAt( GetAvRegionPos(av), 0.01, 0.2 );
                }
                else
                {
                    llStopLookAt();
                    ShowFear( TRUE );
                    // start fleeing
                    SwitchToFleeing( av );
                    
                }
            }   
        }
    }
}

default
{
    state_entry()
    {
        llSetText( "", <1,1,1>, 0.0 );
        useDebug = FALSE;
        if( llGetObjectDesc() == debugObjDesc )
        {
            useDebug = TRUE;
        }
        
        llDeleteCharacter(); // always start with this - clears the object.
        CreateCalmChar();
        
        my_home = llGetPos();
        llWanderWithin( my_home, WANDER_RANGE, [WANDER_PAUSE_AT_WAYPOINTS, TRUE]);
        Debug("Wandering...");
        
        ShowFear( FALSE );
        llCollisionSound( "", 0.0 );
        
        sensor_waiting = FALSE;
        llSetTimerEvent( TICK );
        
        llStartObjectAnimation( walkanimation );
        flagIsIdle = FALSE;
    }
    
    timer()
    {
        llSetTimerEvent( 0.0 );
        
        // The script can only have one sensor event queued at a time.
        // If we add a second, the first one never gets processed.
        if ( sensor_waiting == FALSE )
        {
            llSensor( "", NULL_KEY, AGENT, SENSE_DISTANCE, PI );
            sensor_waiting == TRUE;
        }
        
        llSetTimerEvent( TICK );
    }
    
    sensor( integer n )
    {
        sensor_waiting = FALSE;
        
        float closest_av_dist = MIN_SCARE_RANGE;
        key closest_av = NULL_KEY;
        
        integer x = 0;
        vector pos;
        key av;
        float dist;
        
        for ( ; x < n; ++x )
        {
            av = llDetectedKey(x);
            pos = llDetectedPos(x);
            dist = llVecDist( llGetPos(), pos );
            
            
            if ( dist < MIN_SCARE_RANGE )
            {
                if ( dist < closest_av_dist )
                {
                    closest_av = av;
                    closest_av_dist = dist;
                }
            }
        }

        DoSomething(closest_av);
    }
    
    no_sensor()
    {
        sensor_waiting = FALSE;
        DoSomething(NULL_KEY);
    }

    
    touch_start(integer total_number)
    {
        if ( llDetectedKey(0) == llGetOwner() )
        {
            llSetTimerEvent( 0.0 );
            Debug("Stopping. Reset my script to start me again.");
            
            list temp = llGetObjectAnimationNames();
            integer n = llGetListLength( temp );
            for ( --n; n > -1; --n )
            {
                llStopObjectAnimation( llList2String(temp,n) );
            }
            
            llDeleteCharacter(); // Revert back to a normal prim on touch
        }
    }
    path_update(integer type, list reserved) {
        if (type == 0) {
            Debug("Near");
            return;
         } else if(type == 1) {
            Debug("Stopping");
            DoWhileCurious();
            DoAttack();
            return;
        }
       
        if (type == PU_FAILURE_UNREACHABLE
        || type == PU_FAILURE_INVALID_GOAL
        || type == PU_FAILURE_INVALID_START
        || type == PU_FAILURE_TARGET_GONE
        || type == PU_FAILURE_NO_VALID_DESTINATION
        || type == PU_FAILURE_NO_NAVMESH)
        {   llExecCharacterCmd(CHARACTER_CMD_SMOOTH_STOP, []);
            llOwnerSay("Failed to reach goal. Path update status: " + path_err_msg(type));
            return;
        }
        if (type == PU_GOAL_REACHED)
        {   llOwnerSay("Reached goal.");
            llExecCharacterCmd(CHARACTER_CMD_STOP, []);
            return;
        }
       //llOwnerSay("Other path update:  " + path_err_msg(type));
        
       
    }
    
}

 

Link to comment
Share on other sites

  • 2 weeks later...

@Q Linden

*********UPDATE *******SOLVED *****************
This why my large code would not work there is a bug in the LSL TargetRemove( that does for some unfathomable reason does *not* clear its contents of the key it is clearing  secondly I can see further problems in this routine as it only seems to issue a 0 or 1 no key  value you cant send these keys through procedures giving it a real headache why doesn't LSL look at these thing when it adds code like TargetRemove( to be honest its not a good workable solution and LSL needs to fix it can you suggest this to them please?

MR Linden Why cant you do this :

 integer __llTargetRemove(integer _id){
    llTargetRemove(_id);
    return 0;
}

Edited by VirtualKitten
added code
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1167 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...