Mon second robot...

Répondre
Partager Rechercher
Pour ceux qui ont participé à l'épisode précédent..

https://forums.jeuxonline.info/showthread.php?t=1024861



je vous propose d'aller explorer plus avant les possibilités du LSL....

Nous avions vu comme faire un automate à mémoire. On enregistrait les positions et rotations de l'avatar et on pouvait les "rejouer" après...

Pour ce second robot on va créer un script de départ appeler Engine 1

dans un objet nommé Robot.

C'est un robot qui suit son maître simplement et nous verrons, si le sujet intéresse, comment ajouter des modules pour le rendre ... indispensable ;-).
Citation :
Création de RoboT en 10 secondes...

1. Créer un sphere pas une ...box

2. Créer un script de départ ( Edit/Content/New Script)

3. Remplacer le part celui ci-dessous.

4. Compiler le

5. Admirer sa bouille sympa et la façon sympa de vous suivre en douceur et lévitation...
Le Script ( nommé le Engine 1.0)

Code PHP:

// _________ Globales Variables __________//

// Common Variables //
string      Object_Name =   "RoboT";
string      Version     =  "v1.0";
key         Owner;
float       Timer 0.4;
integer     On_Off FALSE;

// Follow me variables//
vector      Pos;
rotation    Rot;
list        
Pos_Rot;

Infos()
{
    if ( 
On_Off)
        
llOwnerSay ( (string) llVecMag(Pos llGetPos()) );
}

Follow_Me() // Move the robot...
{
    
Pos_Rot     llGetObjectDetails(Owner, [ OBJECT_POSOBJECT_ROT]);
    
vector size llGetAgentSize(Owner);
    
Pos llList2Vector (Pos_Rot,0);    // Get where is the owner in the region
    
Rot llList2Rot (Pos_Rot,1);       // position & rotation 
    
    
Infos();
    
    
llMoveToTarget(Pos + <1.0,1.0,size.y/2>*Rot ,0.6);              // move ...
    
llRotLookAt(Rot llEuler2Rot(<PI,0.0PI>)  ,0.4,0.6);   // ... & rotate
}


Build_Robot() // Used once at creation...
{
    
llSetObjectName (Object_Name);
    
llSetObjectDesc (Version);
    
llSetScale(<.25,.25,.25>);
    
llSetPrimitiveParams([  PRIM_TEXTURE
                                
ALL_SIDES,"fbe9f069-9696-6b3f-e58c-beaf3ce0f1ed", < 0.4,1.0,0.0>, <1.0,1.0,0.0>, 0.0
                            
PRIM_MATERIAL,
                                
PRIM_MATERIAL_WOOD
                            
PRIM_FULLBRIGHT,
                                
ALL_SIDES,TRUE]); 
}

Init()
{
    
Owner llGetOwner();
    
llSetStatus STATUS_PHYSICS,TRUE);
    
llSetTimerEvent (Timer);
}
default
{
    
on_rez (integer start_param)
    {
        
Init();    
    }
    
state_entry()
    {
        if ( 
llGetObjectName() == "Object")
            
Build_Robot(); // At the creation only...
        
Init();
    }
    
    
touch_start(integer num)
    {
        
On_Off =!On_Off;
    }

    
timer()
    {
       
Follow_Me();
    }

Le RoboT


ScreenHunter_155.jpg
Citation :
Publié par Seb_01

C'est un robot qui suit son maître simplement et nous verrons, si le sujet intéresse, comment ajouter des modules pour le rendre ... indispensable ;-).
J'adore l'idée Seb

Il y a un petit moment j'avais trouvé un script proposé par un anglais en OpenSource (je redonnerai le lien quand j'aurai 5 mins) qui faisait interagir le robot verbalement avec un avatar. Ils avaient une conversation certes limitée à quelques Questions/Réponses mais c'était vraiment sympa.

Si mes souvenirs sont bon le Robot analysait le vocabulaire ainsi que l'intonation de son interlocuteur (question, affirmation, négation, formules de politesses etc.) et cherchait les combinaisons de mots adéquates qu'il avait stocké dans son lexique. Seul inconvénient, le script était une usine...
Analyse de l' Engine v1.0:

La seule fonction qui nous intéresse est Follow_Me

Code PHP:

Follow_Me() // Move the robot...
{
    
Pos_Rot     llGetObjectDetails(Owner, [ OBJECT_POSOBJECT_ROT]);
    
vector size llGetAgentSize(Owner);
    
Pos llList2Vector (Pos_Rot,0);    // Get where is the owner in the region
    
Rot llList2Rot (Pos_Rot,1);       // position & rotation 
    
    
Infos();
    
    
llMoveToTarget(Pos + <1.0,1.0,size.y/2>*Rot ,0.6);              // move ...
    
llRotLookAt(Rot llEuler2Rot(<PI,0.0PI>)  ,0.4,0.6);   // ... & rotate

On récupère la position et la rotation de l'owner et on effectue l'ajustement du robot avec ces paramètres + un offset ( 1 m à gauche, 1 m devant et à la hauteur de la moitié de la taille du owner).

Le tout étant cadencé par le timer

Code PHP:

llSetTimerEvent (Timer); //  Timer = .4 

Cela fonctionne correctement malgré un nombre limité d'instructions.


Plusieurs problèmes sont à prendre en considération rapidement:
Citation :
  • Quelque soit la mobilité du owner, le timer reste fixe ( 1/0.4s = 2.5 events/s)
Ce qui peut présenter des désavantages ( pas assez rapide dans les déplacements à haute vitesse et consomme des ressources inutiles si le owner est statique ).
  • Le timer ne tient pas compte de la présennce du owner
Consommation inutile de resources.
  • Le robot peut rester coincé/bloqué à une frontière ou les déplacements d'objets sont interdits
Cas fréquent et un peu cata. Cette situation chronique en a découragé plus d'un...


I Gestion du timer.



On doit détecter la présence du owner. Cela est rendu possible facilement par 2 fonctions existantes:

llGetObjectDetails(..) & llGetAgentSize(...) qui retournent respectivement une liste vide et un vecteur à zéro si l'owner n'est pas sur la région de RoboT.

Ce qui nous permet d'écrire:

Code PHP:

    if ( size ==  ZERO_VECTOR || llGetListLength(Pos_Rot) == // the owner seems be not here..
    
{
        
llSetTimerEvent (5);            // then check it only each 5 seconds 
        
return;
    } 
Au moins quand le chat n'est pas là on est cool..

NB: chacun met la valeur qu'il veut ici .... 30 secondes ou plus est totalement possible, mais à savoir qu'au retour du owner on se devra d'attendre la fin du timer en cours...pour voir arriver le RoboT.


Il nous faut connaitre la distance entre le Owner et son robot pour avoir une base de travail.

Vite fait une fonction...

Code PHP:

float Distance(vector pos1vector pos2)
{
    return 
llVecMagpos1pos2);    // get distance btw 2 positions

Maintenant nous pouvons imaginer le code suivant:

Code PHP:

    float dist =  Distance(Pos,llGetPos()); // calculate the distance btw owner & robot

    
if (dist <= 1.5 )                   // (1.445) is the distance when nothing move then slow down the timer   
        
Timer 1;                         // slow down the timer
    
else
        
Timer .2;                     //  set timer a interval shorter 
    
    
llSetTimerEvent (Timer); // .. and set it! 
Vérifions..
Citation :
4:18] RoboT: Distance => 1.322158 Timer => 1.000000
[4:18] RoboT: Distance => 1.424765 Timer => 1.000000
[4:18] RoboT: Distance => 3.919860 Timer => 0.200000
[4:18] RoboT: Distance => 4.543926 Timer => 0.200000
[4:18] RoboT: Distance => 4.027441 Timer => 0.200000
[4:18] RoboT: Distance => 3.117732 Timer => 0.200000
[4:18] RoboT: Distance => 2.049939 Timer => 0.200000
[4:18] RoboT: Distance => 1.357219 Timer => 1.000000
[4:18] RoboT: Distance => 1.178270 Timer => 1.000000
[4:18] RoboT: Distance => 1.396050 Timer => 1.000000
Cela prend forme...

Par contre lors d'un déplacement haute vitesse de l'avatar on constate que RoboT à du mal à suivre:

Citation :
[4:20] RoboT: Distance => 37.152970 Timer => 0.200000
[4:20] RoboT: Distance => 44.077800 Timer => 0.200000
[4:20] RoboT: Distance => 50.484330 Timer => 0.200000
[4:20] RoboT: Distance => 53.966030 Timer => 0.200000
[4:20] RoboT: Distance => 39.432010 Timer => 0.200000
[4:20] RoboT: Distance => 47.091770 Timer => 0.200000
[4:20] RoboT: Distance => 47.540090 Timer => 0.200000
[4:20] RoboT: Distance => 34.609540 Timer => 0.200000
[4:20] RoboT: Distance => 24.696530 Timer => 0.200000
[4:20] RoboT: Distance => 17.650830 Timer => 0.200000
[4:20] RoboT: Distance => 12.655410 Timer => 0.200000

[4:20] RoboT: Distance => 9.108842 Timer => 0.200000
[4:20] RoboT: Distance => 6.608610 Timer => 0.200000
[4:20] RoboT: Distance => 4.545148 Timer => 0.200000
[4:20] RoboT: Distance => 3.755084 Timer => 0.200000
[4:20] RoboT: Distance => 2.894618 Timer => 0.200000
[4:20] RoboT: Distance => 2.326331 Timer => 0.200000
[4:20] RoboT: Distance => 1.964801 Timer => 0.200000
[4:20] RoboT: Distance => 1.743668 Timer => 0.200000
[4:20] RoboT: Distance => 1.612678 Timer => 0.200000
[4:20] RoboT: Distance => 1.536502 Timer => 0.200000
[4:20] RoboT: Distance => 1.492293 Timer => 1.000000
[4:20] RoboT: Distance => 1.445624 Timer => 1.000000
On peut améliorer les démarrages du Robot on lui ajoutant une sorte de petit KERS (formule 1) ...
Code PHP:

vector direction llVecNorm(Pos llGetPos());
    
llApplyImpulse(direction 1000); 
Je ne rentrerai pas dans les détails de ces fonctions, lire le wiki...héhé

Bref on donne une force (100) pendant un petit bout de temps... A défaut d'être spectaculaire (à ce stade) les mouvements sont plus souples (le damp freine l'impulsion ici...)
Cela ne règle toujours pas le fait que petit robot se fait larguer...

On va donc lui adjoindre le mode Seb's Turbo...


Attention... 2 lignes de code ci dessous sont à proscrire dans 99,9999% des cas,

mais dans celui ci et à défaut d'autre ... je l'ai fait.

Code PHP:

// _________ Globales Variables __________//

// Common Variables //
string      Object_Name =   "RoboT";
string      Version     =  "v1.1";
key         Owner;
float       Timer 0.4;
integer     On_Off FALSE;

// Follow me variables//
vector      Pos;
rotation    Rot;
list        
Pos_Rot;


Build_Robot() // Used once at creation...
{
    
llSetScale(<.25,.25,.25>);
    
llSetPrimitiveParams([  PRIM_TEXTURE
                                
ALL_SIDES,"fbe9f069-9696-6b3f-e58c-beaf3ce0f1ed", < 0.4,1.0,0.0>, <1.0,1.0,0.0>, 0.0
                            
PRIM_MATERIAL,
                                
PRIM_MATERIAL_WOOD
                            
PRIM_FULLBRIGHT,
                                
ALL_SIDES,TRUE]); 
}

Init()
{
    
Owner llGetOwner();
    
llSetObjectName (Object_Name " " Version);
    
llSetObjectDesc ("");
    
llSetStatus STATUS_PHYSICS,TRUE);
    
llSetTimerEvent (Timer);
}


Infos(float distance)
{
    if ( 
On_Off)
        
llOwnerSay "Distance => " + (string)distance +  " Timer => " + (string) Timer);
}

float Distance(vector pos1vector pos2)
{
    return 
llVecMagpos1pos2);
}


Follow_Me() // Move the robot...
{
@
Turbo_Mode// Label //
    
    
Pos_Rot     llGetObjectDetails(Owner, [ OBJECT_POSOBJECT_ROT]); // Get Positions & Rotations
    
vector size llGetAgentSize(Owner);// get the agent size
    
    
if ( size ==  ZERO_VECTOR || llGetListLength(Pos_Rot) == // the owner seems be not here..
    
{
        
llSetTimerEvent (5);            // control only each 5 seconds 
        
return;
    }   

    
Pos llList2Vector (Pos_Rot,0);    // Get where is the owner in the region
    
Rot llList2Rot (Pos_Rot,1);       // position & rotation 
            
    
Pos Pos + <1,1,size.y/2>*Rot;     // correction offset
    
    
vector direction llVecNorm(Pos llGetPos());
    
llApplyImpulse(direction 1000); // Impulse Once ... instead llSetForce (see wiki) 
    
    
float dist =  Distance(Pos,llGetPos()); // calculate the distance btw owner & robot

    
if (dist <= 1.5 )                   // (1.445) is the distance when nothing move then slow down the timer   
        
Timer 1
    else  if (
dist && dist <= )    // if the distance > 1 & < 5 then reduce the timing to move faster
        
Timer .2;                     
    else 
    {                                   
// Entering in Turbo!! 
        
llSetTimerEvent (0); 
        
llMoveToTarget(Pos0.1);  // move only without rotate & damp...
        
if (On_Off)
            
llOwnerSay ( (string)  llVecMag(Pos llGetPos()) );
        
jump Turbo_Mode;   //           // shunt the timer!
    
}
    
    
llSetTimerEvent (Timer); // .. and set it!
    
    
Infos(dist);
    
    
llMoveToTarget(Pos0.6);              // move ...
    
llRotLookAt(Rot llEuler2Rot(<PI,0.0PI>)  ,0.4,0.6);   // ... & rotate
}

default
{
    
on_rez (integer start_param)
    {
        
Init();    
    }
    
state_entry()
    {
        if ( 
llGetObjectName() == "Object")
            
Build_Robot(); // At the creation only...
        
Init();
    }

    
touch_start(integer num)
    {
        
On_Off =!On_Off;
        
llOwnerSay "Aie!");
    }
    
    
timer()
    {
       
Follow_Me();
    }

Pour afficher ou non les infos de distance et de timer cliquez sur le robot...

Voilà une version plus aboutie... mais il reste à gérer les frontières ... interdites.

Mais cela est autre histoire pleine d'astuces..
On va traiter des terrains qui n'acceptent pas le déplacement d'objets.

On a tous reçu un jour ou l'autre un un joli petit message bleu annonçant fugitivement quelque chose comme cela:

Cant move the object XYZ to [vector ] the region ABC don't.. etc

ou

Cant reposition -- permission denied

etc...

Notre robot n'échappe pas à cette interdiction et se retrouve planter à la frontière dans l'impossibilité de se mouvoir plus avant..

2 Fonctions semblent intéressantes :

LlScriptDanger

LlGetParcelFlags


Mais à l'usage elles seront bien décevantes et totalement inefficace pour notre problème.


Prenons la problématique par les faits tout simplement... Le robot est bloqué quand sa mobilité = 0 et que la distance qui le sépare de son propriétaire est < 1.5 m.

La mobilité s'appelle la vélocité est peut être calculée par l'utilisation de 2 fonctions imbriquées :

Code PHP:

llVecMag(llGetVel()) 

Le calcul de la distance entre le owner et le robot est déjà implementée par une fonction.
Code PHP:

float Distance(vector pos1vector pos2// get the distance btw 2 positions
{
    return 
llVecMagpos1pos2);

Nous pouvons donc détecter facilement si le robot est bloqué en créant la fonction suivante:


Code PHP:

integer Check_Trap() // if the robot is stopped by a parcel where objects cant move...
{
    return (
llVecMag(Pos llGetPos() ) > && llVecMag(llGetVel()) == 0.0 );

La détection étant faite ouf! et beaucoup plus facilement qu'en utilisant d'autre fonctions LSL...

Il nous reste à sortir le robot de cette position / situation de blocage.

Le grand hic c'est que:

Quand un objet est "physical" et "bloqué" les mouvements physiques lui sont interdits... llMoveToTarget(..) par exemple.

Quand un objet n'est pas physique et "bloqué" les mouvements lui sont interdits aussi... llSetPos(..)

...mais on peut "forcer" le déplacement par l'utilisation de la fonction :

llSetPrimitiveParams([PRIM_POSITION]..).

Cette fonction est déjà utilisée astucieusement dans 2 hacks (reconnus et tolérés par LL):

Bouger un avatar sur une prim..
Déplacer un objet sur de longues distance en gardant un temps de ... 0.2s.

Nous allons l'utiliser et s'appuyer sur la fonction warPos


L'intégration de cette sécurité sera donc gérée de la façon suivante:

Code PHP:

    if ( Check_Trap() ) // verify if the robot can move
    
{        
        if (++
Attempts )  // +1 and test...
        
{     
            
llSetStatus STATUS_PHYSICS,FALSE);
            
warpPos(Good_Pos);              // move to the last "good" position knew...
            
Timer 1;
            
llSetTimerEventTimer);
            
llSetStatus STATUS_PHYSICS,TRUE);
            
Attempts 1
        }
    }
    else
    {
        
Good_Pos llGetPos(); // if robot moved  then keep trace...
        
Attempts 0;
        
llSetTimerEventTimer_Default); 
    } 
Lorque le robot est bloqué on le détecte et on incrémente le compteur Attempts , après 5 tentatives on décide de le déplacer à la dernière position connue sans blocage. on abaisse le timer à 1 seconde.

Et voilà c'est tout simple


On va profiter de l'intégration de la fonction warpPos on intégrer les grands déplacements >50m comprenant de ce fait les téléportations en altitude.
Code PHP:

        if (dist 50)
        {    
            
llSetStatus STATUS_PHYSICS,FALSE);    // doesnt work with physical objects
            
warpPos(Pos);                           //  famous and knew hack of LSL
            
llSetStatus STATUS_PHYSICS,TRUE);
            return; 
        } 
Un autre point important pour la sécurité du robot est d'avoir une référence sur le terrain... nous allons donc lui attribuer une position privilégiée appeler Home

L'affection première se fera par défaut sur le rez du robot:


Code PHP:

    if (Home == ZERO_VECTOR)
        
Home llGetPos();                  // If no home set it! 
Un autre élément à mettre en place est le status du robot. En effet par nature et définition un robot peut réaliser une multitude d'opérations diverses et variées. Il convient donc de connaitre à tout moment ce qu'il est en train de faire...

par exemple..
Code PHP:

    Status_Robot Following
Quand un owner disparait de la région le robot se met dans l'attente de son retour en effectuant toutes les secondes un contrôle de présence.

Ce qui pour de longues absences peut s'avérer un peu fastidieux... ( 720 contrôles / heure x nombre d'heures ...)



Gràce à la mise en place des élements ci dessus nous pouvons mettre en place un système plus... adéquat.

Code PHP:

    if ( size ==  ZERO_VECTOR || llGetListLength(Pos_Rot) == // the owner seems be not here..
    
{
        
llSetTimerEvent (5);            // control only each 5 seconds 
        
if (++N_Before_Sleep <60)
            return;
        else
        {
            
llSetTimerEvent(0);   // Stop timer
            
N_Before_Sleep 0;
            
Status_Robot Sleeping;
            
llSetText "zzzZZZZ", <1.01.01.0 >, 1.0);
            
warpPos Home  );    // ... and go Sleep
             
        
}
    }  
    else
      
N_Before_Sleep =0
Si le owner disparait 60 * 5 s = 5 minutes le robot rejoint sa Home et stoppe ces contrôles. Il entre en "Sleeping"

pour le réveiller on clique sur sa tête..

Code PHP:

    touch_start(integer num)
    {
        if (
Status_Robot == Sleeping)
        {
            
llSetTimerEvent (Timer_Default);    
            
llSetText "", <1.01.01.0 >, 0.0);
        }
   } 
Voila on a doté le robot d'outils lui permettant de vivre sa vie sereinement...


La version Engine 1.2 du script.

Code PHP:

// _________ Globales Variables __________//

// Constants //
string      Object_Name   =    "RoboT";
string      Version       =    "v1.1";
key         Texture       =    "fbe9f069-9696-6b3f-e58c-beaf3ce0f1ed";
integer     Sleeping      =  0;
integer     Following     =  1;
float       Timer_Default =  0.4;


// Build Constants & variables //
float       Alpha       =   0.0;
vector      Repeats     =   <0.4,1.0,0.0>;
vector      Offset      =   <1.0,1.0,0.0>; 
vector      Size_RoboT  =   <.25,.25,.25>;
vector      Home        =   ZERO_VECTOR;
integer     N_Before_Sleep;
integer     Status_Robot;    


// Common Variables //
key         Owner;
float       Timer 0.4;
integer     On_Off FALSE;

// Follow me variables//
vector      Pos;
vector      Good_Pos;
rotation    Rot;
list        
Pos_Rot;
integer     Attempts;


Build_Robot() // Used once at creation...
{
    
llSetScale(Size_RoboT);
    
llSetPrimitiveParams([  PRIM_TEXTURE,ALL_SIDES,TextureRepeatsOffsetAlpha
                            
PRIM_MATERIAL,PRIM_MATERIAL_WOOD
                            
PRIM_FULLBRIGHT,ALL_SIDES,TRUE]); 
}

Init() // on reset or rez
{
    
Owner llGetOwner();
    
llSetObjectName (Object_Name " " Version);
    
llSetObjectDesc ("");
    
llSetStatus STATUS_PHYSICS,TRUE);     // Put the robot in physical mode
    
if (Home == ZERO_VECTOR)
        
Home llGetPos();                  // If no home set it!
    
Status_Robot Following;               // First status
    
llSetText "", <1.01.01.0 >, 0.0); // clear Hover Text
    
llSetTimerEvent (Timer);                // start following
}


Infos(float distance)
{
    if ( 
On_Off)  // on click on robot  we can show these infos
        
llOwnerSay "Vitesse => " + (string) llVecMag(llGetVel()) + " Distance => " + (string)distance +  " Timer => " + (string) Timer);
}

float Distance(vector pos1vector pos2// get the distance btw 2 positions
{
    return 
llVecMagpos1pos2);
}


warpPos(vector target)
{    
// for looong trips... // http://wiki.secondlife.com/wiki/WarpPos //
    
integer jumps = (integer) (llVecDist(targetllGetPos()) / 10.0) + 1;
    if (
jumps 411)
        
jumps 411;
    list 
rules =[PRIM_POSITIONtarget];    //The start for the rules list
    
integer count 1;
    while ((
count count << 1) < jumps)
        
rules += rules;
    
llSetPrimitiveParams(rules llList2List(rules, (count jumps) << 1count));
}

integer Check_Trap() // if the robot is stopped by a parcel where objects cant move...
{
    return (
llVecMag(Pos llGetPos() ) > && llVecMag(llGetVel()) == 0.0 );
}


Follow_Me() // Move the robot...
{
@
Turbo_Mode// Label //
    
    
Pos_Rot     llGetObjectDetails(Owner, [ OBJECT_POSOBJECT_ROT]); // Get Positions & Rotations
    
vector size llGetAgentSize(Owner);// get the agent size
    
    
if ( size ==  ZERO_VECTOR || llGetListLength(Pos_Rot) == // the owner seems be not here..
    
{
        
llSetTimerEvent (5);            // control only each 5 seconds 
        
if (++N_Before_Sleep 120)
            return;
        else
        {
            
llSetTimerEvent(0);   // Stop timer
            
N_Before_Sleep 0;
            
Status_Robot Sleeping;
            
llSetText "zzzZZZZ", <1.01.01.0 >, 1.0);
            
warpPos Home  );    // ... and go Sleep
             
        
}
    }  
    else
      
N_Before_Sleep =0;   

    
Pos llList2Vector (Pos_Rot,0);    // Get where is the owner in the region
    
Rot llList2Rot (Pos_Rot,1);       // position & rotation 
            
    
Pos Pos + <1,1,size.y/2> * Rot;   // correction offset
    
    
vector direction llVecNorm(Pos llGetPos());
    
llApplyImpulse(direction 1000); // Impulse Once ... instead llSetForce (see wiki) 
    
    
float dist =  Distance(Pos,llGetPos()); // calculate the distance btw owner & robot
    
    
if ( Attempts == // Dont must be trapped to get a best timer...
    
{
        if (
dist 50)
        {    
            
llSetStatus STATUS_PHYSICS,FALSE);    // doesnt work with physical objects
            
warpPos(Pos);                           //  famous and knew hack of LSL
            
llSetStatus STATUS_PHYSICS,TRUE);
            return; 
        }
        if (
dist <= )                   //  [(1.445) is the distance btw robot and owner in quiet state... 
            
Timer 1
        else  if (
dist && dist <= )    // if the distance > 1 & < 5 then reduce the timing to move faster
            
Timer .2;                     
        else 
        {                                   
// Entering in Turbo Mode!!
            
if ( Check_Trap() )             //  Trapped in turbo mode?
                
++Attempts;                 //  if yes then  record it
                
            
llSetTimerEvent (0); 
            
llMoveToTarget(Pos0.1);  // move only without rotate & damp...
            
if (On_Off)
                
llOwnerSay "Vitesse => " + (string) llVecMag(llGetVel()) + " Distance => " + (string)llVecMag(Pos llGetPos()));
            
jump Turbo_Mode;   //           // shunt the timer!
        
}
    }
    
    
llSetTimerEvent (Timer); // .. and set it!
    
    
Infos(dist); // show infos if autorized...
    
    
llMoveToTarget(Pos0.6);              // move ...
    
llRotLookAt(Rot llEuler2Rot(<PI,0.0PI>)  ,0.4,0.6);   // ... & rotate
    
    //llOwnerSay( (string) llVecMag(Pos - llGetPos()) + " " +  (string) llGetVel());
    
    
    
if ( Check_Trap() ) // verify if the robot can move
    
{        
        if (++
Attempts )  // +1 and test...
        
{     
            
llSetStatus STATUS_PHYSICS,FALSE);
            
warpPos(Good_Pos);              // move to the last "good" position knew...
            
Timer 1;
            
llSetTimerEventTimer);
            
llSetStatus STATUS_PHYSICS,TRUE);
            
Attempts 1
        }
    }
    else
    {
        
Good_Pos llGetPos(); // if robot moved  then keep trace...
        
Attempts 0;
        
llSetTimerEventTimer_Default); 
    }
}

default
{
    
on_rez (integer start_param)
    {
        
Init();    
    }
    
state_entry()
    {
        if ( 
llGetObjectName() == "Object")
            
Build_Robot(); // At the creation only...
        
Init();
    }

    
touch_start(integer num)
    {
        if (
Status_Robot == Sleeping)
        {
            
llSetTimerEvent (Timer_Default);    
            
llSetText "", <1.01.01.0 >, 0.0);
        }
        else
        {
            
On_Off =!On_Off;
            
llOwnerSay "Aie!");
        }
    }
    
    
    
timer()
    {
       
Follow_Me();
    }

Je vous laisse tester cette nouvelle version... si vous detectez des bugs on essayera de les corriger. ; )

C'est déjà un très bon follower... mais manque tout le système de communication, qui permettrait un échange d'infos/d'ordres bien sympathique...

NB: Sur une téléportation dans la même région le robot met ... 0.2s!
Je vais utiliser ton script pour me faire un petit délire que j'ai en tête depuis longtemps... c'est en ayant vu le film "Dune" de D.Lynch... certains personnages ont des lampes volantes qui les suivent partout.. j'ai toujours trouvé cette idée géniale
Pourquoi pas...

pour ajuster la position de ta lampe c'est ici


Code PHP:

    Pos Pos + <1,1,size.y/2> * Rot;   // correction offset 

x,y,z sont des coordonnées locale ( 1 m, 1m , 1/2 de la hauteur de l'avatar)
Tu crées une fonction Distance()
Code PHP:

float Distance(vector pos1vector pos2// get the distance btw 2 positions
{
    return 
llVecMagpos1pos2);

Pourquoi faire une fonction dont l'appel pénalise les performances quand une fonction native LSL existe ?
llVecDist
Une meilleur alternative au warpPos :

http://wiki.secondlife.com/wiki/PosJump

Beaucoup plus rapide, moins laggy et contrairement au warpPos ne bouffe pas énormément de mémoire même pour faire des sauts de plus de 4 000 mètres. En attendant d'intégrer une fonctionnalité (officielle) pour le LSL capable de déplacer un objet sur de très longues distances, ce second hack marchera (plus d'infos ici ).


Il y a une petite faille dans ton raisonnement, pour une parcel no object entry ça ne posera pas de problèmes si un objet essaye de rentrer dedans, par contre pour les no script parcel c'est une autre histoire .

llGetParcelFlags est très efficace justement pour empêcher ce genre d'erreur. Apès survient un autre problème : La parcel peut être no script, mais le owner de l'objet peut quand même avoir les droits (il peut être le owner de la land ou tout simplement dans le groupe attaché à cette land). Pour ça je check le owner de la land par rapport au llGetOwner ainsi que le groupe de l'objet par rapport à celui de la land (mais évidemment, il n'y a pas de solutions fiables à 100%).
Citation :
Publié par Mingyar Ishtari
Tu crées une fonction Distance()
Code PHP:

float Distance(vector pos1vector pos2// get the distance btw 2 positions
{
    return 
llVecMagpos1pos2);

Pourquoi faire une fonction dont l'appel pénalise les performances quand une fonction native LSL existe ?
llVecDist

Comparons ce qui est comparable...

llVectDist est une fonction système certes tout comme llVectMag que j'utilise ici en est une autre...[ return llVecMag( pos1- pos2); ]
Citation :
Publié par Mingyar Ishtari
Tu crées une fonction Distance()
Code PHP:

float Distance(vector pos1vector pos2// get the distance btw 2 positions
{
    return 
llVecMagpos1pos2);

Pourquoi faire une fonction dont l'appel pénalise les performances quand une fonction native LSL existe ?
llVecDist
Pénaliser les performances en créant une fonction aussi simpliste, j'espère pas sinon on en serait rendu à se demander si l'opération x+y fait laguer la sim.
Citation :
Publié par BlackShade Nightfire
Une meilleur alternative au warpPos :

http://wiki.secondlife.com/wiki/PosJump

Beaucoup plus rapide, moins laggy et contrairement au warpPos ne bouffe pas énormément de mémoire même pour faire des sauts de plus de 4 000 mètres. En attendant d'intégrer une fonctionnalité (officielle) pour le LSL capable de déplacer un objet sur de très longues distances, ce second hack marchera (plus d'infos ici ).


Il y a une petite faille dans ton raisonnement, pour une parcel no object entry ça ne posera pas de problèmes si un objet essaye de rentrer dedans, par contre pour les no script parcel c'est une autre histoire .

llGetParcelFlags est très efficace justement pour empêcher ce genre d'erreur. Apès survient un autre problème : La parcel peut être no script, mais le owner de l'objet peut quand même avoir les droits (il peut être le owner de la land ou tout simplement dans le groupe attaché à cette land). Pour ça je check le owner de la land par rapport au llGetOwner ainsi que le groupe de l'objet par rapport à celui de la land (mais évidemment, il n'y a pas de solutions fiables à 100%).
Linden va créer une fonction warpPos pour remplaçer...le warpPos et conseille de ne pas utiliser le jumpPos qui s'appuie un bug...
Citation :
Andrew Linden added a comment - 08/Apr/09 01:21 PM Turns out the fix that broke posJump was in the LLVector3 class. That is, the simulator code was always correctly trying to handle the bad input from the first PRIM_POSITION input, but a bug in LLVector3::normalize() was preventing it from working correctly when the length went NaN (Not a Number). When the bug was fixed in LLVector3 then LLSetPrimitiveParams() started doing the Right Thing. It is not hard to understand what the Right Thing is in this case. The posJump misfeature, while incredibly useful, was obviously really a bug. Anyone who examined the LSL code involved must conclude that the posJump behavior was not the expected behavior. This is the reason why I don't think posJump has a long term future in SL.
Citation :
Prospero Linden added a comment - 08/Apr/09 03:31 PM OK – PosJump will work again in 1.26.1. **Be aware that it's not going to work forever.** Anybody looking at it should realize that it's rather an ugly hack that takes arcane advantage of a bug in the system.... That bug will get fixed. We're currently discussing what we might be able to do in terms of providing legitimate access to the same functionality.
Je préfère utiliser warpPos.

Le robot n'est pas un outil de téléportation juste que si il a à parcourir une grande distance de temps à autre il le fera en 0.2s ... gagner quelques milli secondes n'a pas d'importance dans ce concept.


Concernant tes remarques sur les flags des lands no script qui n'étaient pas la problématique évoqué dans mon sujet...

Concernant les droits sur les terrains et concernant les objets...

1. Les creations

2. Les entries

3. Les scripts


Les options parcel no object entry et no create object sont activitées sur de TRES nombreux lands et quasi de façon systématique d'où mon intérêt très spécifique et prioritaire.

Donc 2 problèmes sur 3 sont résolus à ce stade

concernant la situation du no script ... si elle est associée au 2 autres le robot s'en sortira. Pourquoi? tout simplement parce que l'objet NE PEUT PAS pénétrer sur le Land!

Donc ce qui veut dire que sur 6 possibilités de blocages 5 sont solutionnées avec une sollution simple et efficace n'est ca pas?

no entry no create no script
==> OK
no entry no create no script ==> OK
no entry no create no script ==> OK
no entry no create no script ==> NOK
no entry no create no script ==> OK
no entry no create no script ==> OK

Pour la 6 ème qui correspond au NO Script seul il me semble qu'elle est rare

mais ce n'est pas une raison j'en conviens... Comme je l'ai déjà indiqué la mise en place est complexe pour toutes les raisons que tu connais ( owner / group et Cie) et plus délicate à gérer.

Finalité elle devra être intégrée un jour ou l'autre pour faire un 6/6

Merci BlackShade de tes remarques toujours pertinantes
Citation :
Publié par BlackShade Nightfire
Pénaliser les performances en créant une fonction aussi simpliste, j'espère pas sinon on en serait rendu à se demander si l'opération x+y fait laguer la sim.
Pour être simpliste elle l'est! lol . Résidu de mes mises au points provoquées par l'utilisation de llVectDist() et solutionnée par llVectMag.

Concernant les fonctions users et de façon plus sérieuse. Un appel à une fonction est simplement un réadressage dans le code (adresse de la routine et retour) réglé par le compilateur et le loader.
L'adressage est in script pour les user's functions et out script pour les LSL functions.
Un appel à une fonction prend < 100 microseconds MAIS à un avantage énorme sur le gain mémoire. Les instructions n'étant présente qu'une seule fois ... dans la routine et non x fois dans le code.
Citation :
Publié par Seb_01
Linden va créer une fonction warpPos pour remplaçer...le warpPos et conseille de ne pas utiliser le jumpPos qui s'appuie un bug...
Rien n'a été décidé encore sur la façon dont ça va être intégré. Ils parlaient même de "désactiver" la limite du llSetPos/llSetPrimitivePararms avec PRIM_POS mais je pense que ce sera effectivement une nouvelle fonction.

warpPos est une fonction qui prend beaucoup de ressources quand il s'agit de faire des sauts de grandes distances et pour la mémoire j'en parle pas. posJump est plus un bug que warpPos c'est certain, mais il a la qualité de ne pas remplir une liste de 10 en 10 par rapport a la distance pour fonctionner.

Citation :
Publié par Seb_01
Le robot n'est pas un outil de téléportation juste que si il a à parcourir une grande distance de temps à autre il le fera en 0.2s ... gagner quelques milli secondes n'a pas d'importance dans ce concept.
C'est pas faux, mais ça m'a également permis de poster une alternative temporaire à ceux qui ne connaissent pas cette fonction. Comme j'ai dit plus haut, pour un objet qui parcourt de longues distances à répétitions, mieux vaut se pencher sur cette solution qui est beaucoup moins "bouffe ressource".


Citation :
Publié par Seb_01
concernant la situation du no script ... si elle est associée au 2 autres le robot s'en sortira. Pourquoi? tout simplement parce que l'objet NE PEUT PAS pénétrer sur le Land!
Je parlais surtout des parcel no script avec l'objet entry activé, je suis très souvent sur des public sandbox et j'en vois pas mal.


Citation :
Publié par Seb_01
Merci BlackShade de tes remarques toujours pertinantes
Derien
Suis ok avec toi dans le fond.

...et suite à tes remarques, je suis en train d'intégrer le cas du no script

Comme cela petit robot sera complètement protégé

Par contre j'ai un gros doute sur :

allow Entry / no create / no script ==> OK

si tu peux vérifier cela me rendrait grand service.

Merci

Seb,
Citation :
Publié par Seb_01
Suis ok avec toi dans le fond.

...et suite à tes remarques, je suis en train d'intégrer le cas du no script

Comme cela petit robot sera complètement protégé

Par contre j'ai un gros doute sur :

allow Entry / no create / no script ==> OK

si tu peux vérifier cela me rendrait grand service.

Merci

Seb,


Le create on s'en préoccupe pas tout simplement parce qu'il diffère selon si tu rez ton objet à l'interieur de la parcel concernée. Le no object entry est pas dangereux contrairement au no script qui pourrait coincer l'objet dans certain cas et empêcher le script de continuer son fonctionnement.

Je dirais pour un objet sans protection :

- Object Entry : No | Script : No --> OK
- Object Entry : Yes | Script : No --> NOT OK
- Object Entry : Yes | Script : Yes --> OK
- Object Entry : No | Script : Yes --> OK

La seconde solution serait de faire du llTakeControl pour que le script fonctionne dans le no script, plus besoin de vérifier ensuite.
Citation :
Publié par BlackShade Nightfire
Le create on s'en préoccupe pas tout simplement parce qu'il diffère selon si tu rez ton objet à l'interieur de la parcel concernée. Le no object entry est pas dangereux contrairement au no script qui pourrait coincer l'objet dans certain cas et empêcher le script de continuer son fonctionnement.

Je dirais pour un objet sans protection :

- Object Entry : No | Script : No --> OK
- Object Entry : Yes | Script : No --> NOT OK
- Object Entry : Yes | Script : Yes --> OK
- Object Entry : No | Script : Yes --> OK

La seconde solution serait de faire du llTakeControl pour que le script fonctionne dans le no script, plus besoin de vérifier ensuite.
L'astuce du TakeControl fonctionne dans un objet non attached?

Visiblement oui :

If a script has taken controls, it and other scripts in the same prim will not be stopped if the Agent enters a No-Script Area. This is done to keep vehicle control alive and AOs functional. This is an intentional feature. These scripts will stop working if they call certain blacklisted functions.

Par contre blacklisted functions contient quoi ? lol
Citation :
Publié par Seb_01
L'astuce du TakeControl fonctionne dans un objet non attached?

Visiblement oui :

If a script has taken controls, it and other scripts in the same prim will not be stopped if the Agent enters a No-Script Area. This is done to keep vehicle control alive and AOs functional. This is an intentional feature. These scripts will stop working if they call certain blacklisted functions.

Par contre blacklisted functions contient quoi ? lol
Ouep ça fonctionne en non attached, par contre pour les fonctions blacklisted j'en ai aucune idée, j'étais même pas au courant lol. Un script fonctionne au dessus d'une certaine hauteur en no script, takecontrol ou non. Je crois que c'est au dessus de 100 mètres mais ça reste à vérifier.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés