Il arrive parfois que des scripts puissent s'arrêter d'eux-même à cause d'erreurs. Le run-time error qui peut être le résultat de plusieurs choses va mettre le script en "not running" et ne continuera pas de fonctionner correctement.
Il peut s'agir d'une collision entre la stack et la heap lorsque le script demande une mémoire trop importante, d'une erreur de calcul comme diviser un nombre par zéro (même si en théorie ce calcul est tout à fait possible, il en résulte un nombre infini).
Le problème est qu'il est impossible de ré-activer automatiquement par script un autre qui vient d'être stoppé par un run-time error, la fonction llSetScriptState et llResetOtherScript par exemple ne fonctionnera pas.
Il est par contre tout à fait possible de ré-activer un script après le redémarrage de l'objet (re-rez, re-wear). Voici les 2 scripts en question :
Repair Listener (à mettre dans un autre prim que le root)
InitConnection() {
llListenRemove( gListenId );
gListenId = llListen( DEBUG_CHANNEL, "", llGetLinkKey(LISTEN_LINK), "" ); // on active l'écoute du linked prim correspondant sur DEBUG_CHANNEL
}
integer IC_SCRIPTREP_ADD = -258954; // adresse du script qui va s'occuper de reset
integer LISTEN_LINK = 1; // 1 = root prim
integer gListenId;
default
{
on_rez( integer p ) { InitConnection(); }
state_entry() { InitConnection(); }
listen( integer chan, string name, key id, string msg ) {
if( ~ llSubStringIndex(msg, "run-time error") ) // si "run-time error" est présent dans msg alors on envoie le nom du script par linked message
llMessageLinked( LISTEN_LINK, IC_SCRIPTREP_ADD, llGetSubString(msg, llSubStringIndex(msg, ":")+1, llSubStringIndex(msg, "]")-1), NULL_KEY );
}
}
Repair Core (à mettre dans le root prim)
AddScript( string scriptName ) {
if( !~ llListFindList(gScriptList, [scriptName]) ) { // si le nom n'est pas déjà présent dans la liste, on l'ajoute
gScriptList += scriptName;
llOwnerSay( scriptName + " sera reset au prochain demarrage." );
}
}
RepairScript() {
integer m = (gScriptList!=[]); // on compte le nombre de noms dans la liste
string scriptName;
while( ~--m ) {
scriptName = llList2String( gScriptList, m ); // on récupère le nom de la liste
if( llGetInventoryType(scriptName) == INVENTORY_SCRIPT ) { // si le script est bien présent dans l'inventaire et qu'il s'agit bien d'un script
llOwnerSay( "Reset : " + scriptName );
llResetOtherScript( scriptName ); // on reset
llSetScriptState( scriptName, TRUE ); // on le reactive
}
}
gScriptList = []; // on vide la liste
}
integer IC_SCRIPTREP_ADD = -258954; // adresse pour ajouter un script
list gScriptList; // liste des scripts à reset
default
{
on_rez( integer p ) { RepairScript(); }
link_message( integer link, integer adress, string data, key data2 ) {
if( adress == IC_SCRIPTREP_ADD ) // on reçoit une demande d'ajout de script à reset
AddScript( data );
}
}
Le fonctionnement :
Le principe est
très simple, j'utilise dans un premier temps "Repair Listener", il s'agit d'un script qui va écouter le DEBUG_CHANNEL (là où les erreurs sont envoyées). Il faudra mettre ce script dans un autre prim que celui où vous souhaitez réparer vos scripts (la raison est qu'un prim ne peut pas s'écouter lui-même quand il envoie des messages dans un canal). Il va envoyer le nom du script qui a une erreur type "run-time error" au Repair Core.
Le Repair Core, lui, va s'occuper de stocker les noms reçus dans une liste puis les reset/activer au prochain démarrage de l'objet, c'est à dire quand :
- Vous re-portez l'objet
- Vous re-rezzez l'objet
Si vous ne comprenez pas tout, demandez-moi de réexpliquer ou si vous avez une meilleur méthode que celle-là, merci de la partager

.