Je propose de mettre en commun tous les trucs et astuces connus et moins connus qui remplissent vos scripts, qu'ils soient issus de vos lectures pertinentes ou de votre propre imagination et expérience qu'importe! Partagez les ...
- Ce wiki ne doit pas être un lieu de messages, afin de qu'il garde une structure lisible et bien organisée.
- Chaque entrée devra commencer par petite explication.
- Un exemple de code possible, clair et commenté facilitant la lecture et la compréhension est de rigueur.
- Les ligne de codes LSL présentées doivent utiliser les balises PHP pour garantir leur structure de code LSL.
- Un petit commentaire final sur l'utilisation ou les limites de l'astuce sera le bien venu.
Merci de respecter ces petites clauses pour le bien de tous.
Seb,
PS:
Si un astuce / truc ne fonctionne pas ou plus, présente des limites non énoncées etc... déposez une alerte chez le dépositaire si pas de réaction intervenez ici.
-Pour insérer un article-
1. Sélectionner modifier le wiki.
2. Entrer vote titre entre les balises [titre]Votre titre[/titre].
3. Laisser 1 ligne blanche.
4. Entrer votre nom en gras entre les balises [b]By Votre Nom[/b].
5. Laisser 3 lignes blanches.
6. Insérer votre article.
7. Entrer le motif de modification.
8. Enregistrer.
Un chrono moins chahuté par le lag...
Par Seb_01
llGetTime ()
Script time does not measure time dilation. To measure elapsed calendar time, call llGetTimestamp instead, since time dilation and resets often make dilated time intervals differ from calendar time intervals.
Deux routines au choix...
float Start1;
float Stop1;
float Start2;
float Stop2;
float time1()
{
string stamp = llGetTimestamp();
// "YYYY-MM-DDThh:mm:ss.ff..fZ"
return (integer) llGetSubString(stamp, 11, 12) * 3600 + // hh
(integer) llGetSubString(stamp, 14, 15) * 60 + // mm
(integer)llGetSubString(stamp, 17, 18) + // ss.ff..f
(float)llGetSubString(stamp, 20, -2)/1000000; // ss.ff..f
}
float time2()
{
list parts = llParseString2List(llGetTimestamp(), ["-", "T", ":", ".", "Z"], []);
// "YYYY-MM-DDThh:mm:ss.ff..fZ"
return (integer) llList2Integer( parts, 3) * 3600 +
(integer) llList2Integer( parts, 4) * 60 +
(integer) llList2Integer( parts, 5) +
(float) llList2Integer( parts, 6)/1000000.0;
}
default
{
touch_start(integer total_number)
{
llResetTime();
Start1 = time1();
Start2 = time2();
}
touch(integer total_number)
{
Stop1 = time1();
Stop2 = time1();
float stop_clic = llGetTime();
llOwnerSay( ( (string) (Stop1 - Start1 )+ " " +(string) (Stop2 - Start2 )+ " " + (string) stop_clic));
}
}
Résultats:
[9:32] Object: 1.234375 1.042969 1.997158
[9:32] Object: 0.347656 0.347656 0.349688
[9:32] Object: 0.835938 0.835938 0.839702
[9:32] Object: 1.382813 1.382813 1.377903
[9:32] Object: 1.839844 1.839844 1.844050
[9:32] Object: 2.332031 2.332031 2.341316
[9:32] Object: 2.726563 2.726563 2.732766
[9:32] Object: 3.214844 3.214844 3.219509
[9:32] Object: 5.109375 5.109375 5.116445
Création d'un tableau à 2 dimensions
Par Seb_01
Les Arrays font bien défaut dans LSL pourtant il existe un petit script de Sandie qui permet de palier à cela.
Je trouve l'algorithme astucieux et l'utilisation finale vraiment très simple.
Je vous laisse le lien
ICI
Communiquer entre scripts dans une prim
Par Seb_01
En complément de l'astuce
==>
Communication entre scripts
Lorsque que l'on a à communiquer entre scripts situés dans une prim on a recours à l'utilisation du champs num pour établir son aiguillage :
Script A
touch_start( integer n )
{
llMessageLinked( LINK_THIS, 123456, "message", "" );
}
Script B
link_message( integer link, integer num, string message, key id)
{
if( adress == 1000)
{ ... }
}
Mais quand on a plusieurs scripts qui interagissent ensemble l'affectation ou l'utilisation d'un simple numéro demande un certaine discipline ou rigueur.
On peut affecter un range au script A [ 100- 200] B [ 1000 2000] etc...
chacun sa méthode ou son organisation mais cela reste des numéros...
Il m'arrive alors de changer ce style d'adressage par celui là :
Script A
touch_start( integer n )
{
llMessageLinked( LINK_THIS, 0, "message", "Script B" );
}
Script B
link_message( integer link, integer num, string message, key script)
{
if( (string) script == llGetScriptName())
{ ... }
}
si on a plusieurs type de messages à adresser au script B ...
Script A
touch_start( integer n )
{
llMessageLinked( LINK_THIS, 0, "message", "Script B" );
}
Script A
touch_start( integer n )
{
llMessageLinked( LINK_THIS, 1, "action", "Script B" );
}
Script B
link_message( integer link, integer adress, string message, key script)
{
if( (string) script == llGetScriptName())
{
if( adress == 0)
{ ..}
else if( adress == 1)
{ ..}
}
}
Quand il n'y a pas de message à transmettre style "action" on peut utiliser le champs message pour l'adresse de retour.
Script A
touch_start( integer n )
{
llMessageLinked( LINK_THIS, 1,llGetScriptName(), "Script B" );
}
Script B
link_message( integer link, integer adress, string message, key script)
{
if( (string) script == llGetScriptName())
{
if( adress == 0)
{ ..}
else if( adress == 1)
{
.......
llMessageLinked( LINK_THIS, 0,"données à transmettre", message);
}
}
}
Cela rend les programmes lisibles et pas de prise de tête sur les numéros...
Disposer de plusieurs timers dans un script
Une des faiblesses de lsl est entre autres de n'avoir qu'un seul timer.
Ce qui nous oblige à utiliser des ruses de sioux et des if sur des compteurs, bref vous connaissez tout cela aussi bien que moi.
Un lisant un sujet qui traitait de cela dont l'auteur avait fait une véritable usine à gaz je me suis dis que l'on pouvait plus... simple.
J'ai donc développé 2 petites fonctions qui devraient rendre service un jour ou l'autre à un scripteur confronté à une gestion complexe de timing.
Les fonctions s'utilisent de la façon suivante:
Set_Timer
Set_Timer( "Tempo1",8,ALWAYS); // chaque seconde ALWAYS = -1
Set_Timer( "Tempo2",2,4); // chaque 2 secondes 4 fois
Set_Timer( "Tempo3",6,1); // chaque 6 secondes 1 fois
Set_Timer( "Tempo4",9,1); // chaque 9 secondes 1 fois
Set_Timer( "Tempo5",9,NEVER); // Stoppe le timer
Timer
if (Timer ("Tempo1") ) // sera vrai si le temps est écoulé
Voilà je n'ai pas pu faire plus simple...
Le script incluant un exemple concret de gestion de 4 timers:
//___________________________________________________________________________
integer Time_Timer;
list Base_Events_Time;
integer ALWAYS = -1;
integer NEVER = 0;
//
Set_Timer( string event_time, integer time, integer period )
{
if ( !time)
{
llOwnerSay ( "The Timer cant be set to 0!");
return;
}
integer index = llListFindList ( Base_Events_Time, [event_time] );
if (~index)
if (!period)
{
Base_Events_Time = llDeleteSubList(Base_Events_Time,index, index + 2 );
return;
}
else
Base_Events_Time = llListReplaceList( Base_Events_Time, [ event_time , time, period], index, index + 2 );
else
Base_Events_Time += [ event_time , time, period];
if ( !Time_Timer) llSetTimerEvent(1);
}
//
integer Timer( string event_time )
{
integer index = llListFindList ( Base_Events_Time, [event_time] );
if ( ~index )
{
integer time = llList2Integer( Base_Events_Time, index + 1 );
integer period = llList2Integer( Base_Events_Time, index + 2 );
if ( (Time_Timer%time) == 0 && period != 0 )
{
if ( period != -1 )
{
Base_Events_Time = llListReplaceList( Base_Events_Time, [period-1], index + 2,index + 2 );
Check_Timers();
}
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
//
Check_Timers()
{
integer i; integer len = llGetListLength( Base_Events_Time);
for ( i = 2; i < len; i +=3 )
if (llList2Integer(Base_Events_Time, i) > 0 )
return;
Time_Timer = 0;
llSetTimerEvent(Time_Timer);
}
//___________________________________________________________________________
default
{
state_entry()
{
}
touch_start(integer total_number)
{
// quelques exemples..
Set_Timer( "Tempo1",8,ALWAYS); // chaque seconde
Set_Timer( "Tempo2",2,4); // chaque 2 secondes 4 fois
Set_Timer( "Tempo3",6,1); // chaque 6 secondes 1 fois
Set_Timer( "Tempo4",9,1); // chaque 6 secondes 1 fois
}
timer()
{
++Time_Timer; // Ne pas enlever lol
// afficher le resultats des exemples //
llOwnerSay ((string) (Time_Timer) + " s" );
if ( Timer ("Tempo1") )
llOwnerSay ( "Tempo1" );
if ( Timer ("Tempo2") )
llOwnerSay ( "Tempo2" );
if ( Timer ("Tempo3") )
llOwnerSay ( "Tempo3" );
if ( Timer ("Tempo4") )
{
llOwnerSay ( "Tempo4" );
Set_Timer( "Tempo1",1,NEVER); // stoppe le timer "Tempo1"
}
}
}
Affichera:
[9:27] Object: 1 s
[9:27] Object: 2 s
[9:27] Object: Tempo2
[9:27] Object: 3 s
[9:27] Object: 4 s
[9:27] Object: Tempo2
[9:27] Object: 5 s
[9:27] Object: 6 s
[9:27] Object: Tempo2
[9:27] Object: Tempo3
[9:27] Object: 7 s
[9:27] Object: 8 s
[9:27] Object: Tempo1
[9:27] Object: Tempo2
[9:27] Object: 9 s
[9:27] Object: Tempo4
Avantages:
Gérer un nombre important de différent timers et non 1 seul...
Très simple d'utilisation.
Gestion par événement sous forme de noms
Pas d'utilisation de fonction llSleep
Facilement intégrable dans n'importe quel script.
Inconvénient:
La base de cadencement est de 1 seconde, les timers doivent donc être des multiples de 1 ( 1, 3, 10 etc...)
Lancer ou modifier le temps des timers dans l'event timer lui même peut donner des résultats difficiles à interpréter.
Le principe est très simple basé sur la gestion d'une liste de 3 champs:
L'event_name + le temps du timer + le facteur de répétition ( -1 toujours,0 arrèt, >0 le nombre de fois )
Quand aucun timer n'est actif le cadenceur de 1s est arrêté.