Planet Samuro
Messages
Guest_04104
Planet Samuro
 
Messages
3D Chat
Mini-Chat

Message Panels : General : *** Manuel de référence pour scripter ***
<<<First<<prev.>next.>>>Last>RepReply^Discussion ^vDiscussion vDelDelete the discussion
SamuroSamuro28/03Sent: 28/03/2021 22:55:361 / 1Message 1 from 1

Scripts
=======

Dans chaque objet 3D, vous pouvez ajouter des scripts qui s'exécutent et rendent l'objet vivant.

Ecrire des scripts
------------------
Pour créer un script :
- éditer un objet (Objet > Editer), aller dans le sous-menu "Scripts" et cliquer "Ajouter".
- sélectionner la ligne du script "1 SCR Script" et cliquer "Editer".
- écrire votre script dans l'éditeur et cliquer le bouton "Appliquer".

Dans la liste des script, * indique une erreur de compilation, et ! indique une erreur d'exécution.
Cliquez le bouton "Voir Erreur" dans l'éditeur pour voir les détails de l'erreur.


Librairie Script
================

    Chapitres
    =========
    Evènements
    Conversation
    Mesh
    Objet
    Batches de mouvement
    Avatar
    S'asseoir, animations
    Menus
    Inventaire
    Blocages
    Fichiers Texte
    Données permanentes
    Particules
    Sons
    Media
    Appels Tcpip
    Glisser-déposer
    Conversions
    Manipulation de Strings
    Calendrier
    Math
    Quelques Exemples


Evènements
==========

1. Start
--------

  // start est l'événement initial après que le script soit compilé, que l'objet soit extrait de l'inventaire ou porté sur soi.
  // le script est entièrement réinitialisé lorsqu'il est recompilé, que l'objet est placé dans le monde, ou porté.

  event start ()
  {
    say ("bonjour, je démarre !");
  }


2. Touch
--------

  // l'utilisateur a cliqué sur un objet avec le bouton gauche de la souris
  event touch ()
  {
    key            k       = touched_avatar();
    int            mesh_nr = touched_mesh_nr();
    world_position wp      = touched_world_position();
    vector         v       = touched_mesh_position();

    say ("touched avatar = " + itos(k[0]) + "," + itos(k[1]) + "," + itos(k[2]) + "," + itos(k[3]));
    say ("touched mesh_nr = " + itos(mesh_nr));
    say ("touched world position = " + itos(wp.x) + "," + itos(wp.y) + "," + itos(wp.z));
    say ("touched mesh position = " + ftos(v.x) + "," + ftos(v.y) + "," + ftos(v.z));
  }


Lors du traitement d'un événement TOUCH, les fonctions suivantes peuvent être appelées :

  key touched_avatar ();
  Renvoie une clé permanente unique indiquant l'avatar qui a touché l'objet

  int touched_mesh_nr ();
  Renvoie le numéro de mesh touché (1 à 32)

  world_position touched_world_position ();
  Renvoie la position touchée en coordonnées absolues du monde (voir ci-dessous)

  vector touched_mesh_position ();
  Renvoie la position touchée par rapport au vecteur de centre du mesh (voir ci-dessous)


Les types de données suivants sont prédéfinis :

  typedef int[4] key;    // clé désignant l'identifiant unique d'un avatar

  struct world_position   // une coordonnées absolues sur la planète
  {
    int x, y, z;    // coordonnées en 1/256 mm
  }

  struct vector   // une petite position ou rotation
  {
    float x, y, z;    // coordonnée en m
  }


La fonction same_key() permet de vérifier si deux clés sont identiques :

  bool same_key (key k1, key k2);



3. Collision
------------

  // avatar est entré en collision avec un objet scripté.

  event collision()
  {
    key    k  = collision_avatar();
    int    nr = collision_mesh_nr();
    vector n  = collision_normal();

    say (avatar_name(k) +
         " a collisioné avec mesh nr " + itos(nr)
              + " normal " + ftos(n.x)
                     + " " + ftos(n.y)
                     + " " + ftos(n.z));
  }


L'événement collision est généré lorsqu'un avatar entre en collision avec un objet scripté.

Les fonctions suivantes peuvent être appelées lors d'un événement collision :

  key collision_avatar();      // avatar qui est entré en collision
  int collision_mesh_nr();     // numéro de mesh qui est entré en collision
  vector collision_normal();   // vecteur normalisé avatar vers objet

Les objets ayant la matière COLLISION n'ont pas de physique (comme la matière PHANTOM) mais ils génèrent
un événement collision. Ils peuvent être utilisés comme capteur pour détecter l'arrivée d'un avatar.


4. Listen
---------

  // l'objet écoute parler un avatar

  event listen (key avatar, string message)
  {
    say (avatar_name(avatar) + " a dit " + message);
  }

Lorsqu'un avatar parle, un objet proche reçoit la ligne de chat dans son évènement listen.
Notez que les events listen dans les objets en mouvement doivent être évités, ils ne fonctionnent pas de manière fiable.
La portée par défaut est de 50m mais elle peut être modifiée avec set_listen_range() :

  void set_listen_range (float range);    // set range 0 to 50m, default is 50m.

Lorsqu'il n'est pas utilisé, il est conseillé de régler la portée à 0.0 pour réduire la consommation cpu du serveur.
Pour réduire également la consommation cpu du serveur, vous pouvez définir un filtre pour capturer
uniquement certains messages de chat :

  void set_listen_filter (string filter);

Le filtre par défaut est "*" pour capturer tous les messages.
"*" remplace plusieurs caractères, " ?" remplace un caractère.

Exemple:
  "!*" ne capturera que les lignes de chat commençant par "!", comme "!start" et "!stop".


5. Minuterie
------------

  event start ()
  {
    start_timer (nr => 0, seconds => 3.0);
  }

  // cet événement est appelé à l'expiration d'une minuterie
  event timer (int nr)     // nr is timer number
  {
    say ("timer number " + itos(nr) + " a expiré");
  }

  Chaque script peut démarrer au maximum 16 minuteries (nr de 0 à 15) avec des durées différentes.
  Quand une minuterie expire, l'évènement timer() est appelé avec le numéro de la minuterie qui a expiré.
  Des minuteries périodiques peuvent être créées en redémarrant la minuterie chaque fois qu'elle a expiré,
  cependant, comme cela consomme du cpu, il faut l'utiliser aussi rarement que possible.

  // Exemple:

  event start ()
  {
    start_timer (nr => 0, seconds => 0.0);
  }

  // cet événement est appelé à l'expiration d'une minuterie
  event timer (int nr)     // nr est le numéro de la minuterie
  {
    say ("bonjour !");
    start_timer (nr => 0, seconds => 3.0);   // répéter après 3 secondes
  }



6. Message_Received
-------------------

  event message_received (int sender_object_id, string message)
  {
    say ("reçu : " + message + " de " + itos(sender_object_id));
  }

  L'événement message_received est appelé lorsqu'un autre script envoie un message
  à notre script en utilisant send_message ou broadcast_message.

  void send_message (int object_id, string message);
  void broadcast_message (string script_name, string message);
  key sender_object_owner();    // renvoie le propriétaire de l'objet qui nous a envoyé le message


  // Exemple:

  event touch()
  {
    send_message (object_id => 235,
                  message   => "bonjour à tous les scripts de l'objet 235");

    broadcast_message (script_name => "script1",
                       message     => "bonjour à tous les objets ayant un script appelé script1");
  }


7. Server Restart
-----------------

  event server_restart()
  {
    say ("bonjour, le serveur planet vient de redémarrer");
  }

  L'évènement server_restart est appelé lorsque le serveur planet vient d'être démarré après un certain temps d'arrêt.
  Un script peut utiliser cet événement pour retraiter tout calcul dépendant de l'horloge.


Conversation
============

Say
---

  void say (string value);

  Affichage de texte sur le chat dans un rayon de 20m


  // Exemple:
  event start ()
  {
    say ("Bonjour, je démarre !");
  }


say_to
------

  void say_to (key avatar, string value);

  Idem à say mais destiné à un seul avatar.




Affichage d'icônes
------------------

  event touch ()
  {
    string(32) s;
    int        i;

    s = "";
    for (i=0; i<16; i++)
      s = s + chr(0,i);
    say ("icons : " + s);
  }


Affichage d'images
------------------

  event touch ()
  {
    // nécessite une texture "sun" dans le dossier script de l'objet
    say ("voici mon soleil : " + image ("sun") + " :)");
  }



Ecriture en différentes polices et couleurs
-------------------------------------------

  // message d'accueil

  string font(int f)                                     { return chr(1, f); }
  string style(bool underlined, bool italic, bool bold)  { int s=0; if (underlined) s++; if (italic) s+=2; if (bold) s+=4;  return chr(2, s); }
  string color(int col)                                  { return chr(4, col & 0xFFFF, col>>16); }

  event touch ()
  {
    say ("big "
       + color(0x8080FF)
       + "kiss"
       + font(9)
       + color(0x00FF00)
       + style(underlined => true, italic => true, bold => true)
       + " from Didi");
  }



Mesh
====

Set Mesh Active
---------------

  void set_mesh_active (int mesh_nr, bool enable);

  Rend le mesh actif ou inactif.
  Les meshs inactifs sont invisibles et ne causent aucune collision avec l'avatar.

  // Exemple:
  event start ()
  {
    set_mesh_active (mesh_nr => 1, enable => false);  // désactiver le mesh 1
    set_mesh_active (mesh_nr => 2, enable => true);   // activer le mesh 2
  }


Set Mesh Position
-----------------

  void set_mesh_position (int mesh_nr, vector position);

  Déplace le mesh à l'intérieur d'un objet (de -32.768 à +32.767 m)
  La position est donnée sous forme de vecteur en coordonnées x,y,z.

  // Exemple:
  event start ()
  {
    set_mesh_position (mesh_nr => 1,  position => {1.299, -0.893, 0.5});
  }


Set Mesh Rotation
-----------------

  void set_mesh_rotation (int mesh_nr, vector rotation);

  Permet de faire pivoter un mesh à l'intérieur d'un objet
  La rotation est donnée sous forme d'angles x,y,z en degrés (-360.0 à +360.0)
  L'axe de rotation est le centre 0,0,0 du mesh.

  // Exemple:
  event start ()
  {
    set_mesh_rotation (mesh_nr => 1,  rotation => {0.0, 0.0, 45.0});
  }


Set Mesh Color
--------------

  void set_mesh_color (int mesh_nr, int color);

  Permet de changer la couleur du mesh
  La couleur est définie comme valeur RVB hexadécimale (0xBBVVRR)

  // Exemple:
  event start ()
  {
    set_mesh_color (mesh_nr => 1,   color => 0xFFC0D0);
  }


Set Mesh Transparency
---------------------

  void set_mesh_transparency (int mesh_nr, float transparency);

  Modifie la transparence du mesh
  La valeur de transparence doit être comprise entre 0.0 and 1.0

  // Exemple:
  event start ()
  {
    set_mesh_transparency (mesh_nr => 1,   transparency => 0.3);
  }


Set Mesh Light
--------------

  void set_mesh_light (int   mesh_nr,
                       int   color,
                       float attenuation,  // entre 0.0 et 1.0
                       float range,        // entre 0.0 et 65.0
                       int   cone);        // 0=ponctuelle, ou taille du spot entre 1 et 255.

  Définit une lumière ponctuelle ou spot à la coordonnée 0,0,0 du mesh.
  Pour désactiver la lumière, appeler cette fonction avec distance (range) 0.0

  // Exemple:
  event start ()
  {
    set_mesh_light (mesh_nr => 1, color => 0xFFFFFF, attenuation => 0.6, range => 12.0, cone => 0);
  }


Set Mesh Lightning
------------------

  void set_mesh_lightning (int   mesh_nr,
                           bool  ambiant,   // true = lumière du jour éclaire le mesh
                           bool  sunlight); // true = soleil éclaire le mesh

  Permet de supprimer la lumière du jour ou le soleil qui éclaire le mesh,
  par exemple s'il se trouve dans une cave.

  // Exemple:
  event start ()
  {
    set_mesh_lightning (mesh_nr => 1, ambiant => false, sunlight => false);
  }


Set Mesh Glow
-------------

  void set_mesh_glow (int mesh_nr,
                      int color);

  Permet de faire briller un objet dans le noir.

  // Exemple:
  event start ()
  {
    set_mesh_glow (mesh_nr => 1, color => 0x0000FF);
  }


Set Mesh Uv
-----------

  void set_mesh_uv (int    mesh_nr,
                    int    mode,
                    float  u         = 0.0,
                    float  v         = 0.0,
                    bool   ping_pong = false,
                    bool   one_shot  = false,
                    bool   perlin    = false);

  Faites bouger toutes les textures de ce mesh en changeant l'UV dynamiquement.

  Il y a 6 modes :

  // mode 0 : éteindre UV
  set_mesh_uv (mesh_nr => 1, mode => 0);

  // mode 1 : définir un déplacement U,V fixe
  set_mesh_uv (mesh_nr => 1, mode => 1, u => 0.5, v => 0.3);

  // mode 2 : définir un glissement U,V
  // u, v denote la vitesse du glissement
  set_mesh_uv (mesh_nr => 1, mode => 2, u => 0.1, v => 0.3);

  // mode 3 : images successives
  // la texture doit être constituée de N images de même taille, disposées verticalement.
  // Les images successives sont montrées comme dans un diaporama.
  // u indique le nombre d'images, et v indique la vitesse du changement
  // le paramètre optionnel ping_pong indique si l'on veut afficher les images à l'envers en arrivant à la fin.
  // le paramètre optionnel one_shot indique si nous voulons afficher toutes les images une seule fois, ou les répéter indéfiniment.
  set_mesh_uv (mesh_nr => 1, mode => 3, u => 3.0, v => 100.0);
  set_mesh_uv (mesh_nr => 1, mode => 3, u => 3.0, v => 100.0, ping_pong => true, one_shot => true);

  // mode 4 : texture en rotation
  // u représente l'angle de rotation maximal (360 pour un cercle complet).
  // v indique la vitesse de rotation.
  // le paramètre optionnel ping_pong indique si l'on veut revenir en arrière en arrivant à la fin.
  // la rotation se produit à u,v = 0,0 donc si une rotation centrée est souhaitée
  // vous devez régler l'uv de la texture dans la plage -0.5 à +0.5.
  set_mesh_uv (mesh_nr => 1, mode => 4, u => 360.0, v => 10.0);
  set_mesh_uv (mesh_nr => 1, mode => 4, u => 45.0, v => 80.0, ping_pong => true);

  // mode 5 : texture pulsée
  // u représente l'amplitude de la pulsation.
  // v indique la vitesse.
  // paramètre optionnel ping_pong indique si nous voulons un mouvement de va-et-vient.
  set_mesh_uv (mesh_nr => 1, mode => 5, u => 0.1, v => 100.0);
  set_mesh_uv (mesh_nr => 1, mode => 5, u => 0.1, v => 100.0, ping_pong => true);

  Enfin, l'option 'perlin' peut être activée pour les textures d'eau horizontales.


Set Mesh Texture
----------------

  void set_mesh_texture (int mesh_nr, string texture);

  Remplace la texture de tout un mesh par une nouvelle texture provisoire.
  La nouvelle texture doit être copiée dans le répertoire des scripts de l'objet.
  Un nom de texture vide "" restaure à nouveau la texture originale.
  De même, si vous déposez l'objet sur le terrain il reçoit à nouveau sa texture originale.

  // Exemple:
  event start ()
  {
    set_mesh_texture (mesh_nr => 1, texture => "checkboard");
  }


Objet
=====
int object_id();
  retourne l'ID de l'objet.

bool is_worn ();
  retourne vrai si l'objet courant est porté, faux s'il est créé sur terre.
  (en fait un objet porté a un object_id négatif, un objet sur la terre a un objet id positif)

string object_name ([int object_id]);
  retourne le nom de l'objet (max 32 caractères)

void set_object_name (string name);
  pour un objet porté, change temporairement le nom de l'objet, de sorte que les appels say() utilisent un nom différent.
  pour un objet sur terre, le changement de nom est permanent.

key object_owner ([int object_id]);
  retourne le propriétaire de l'objet.

string object_owner_date ([int object_id]);
  retourne une date en format "YYYYMMDD"

int object_nb_meshes();
  retourne le nombre de meshes de l'objet.

int domain_id();
  return l'id du domaine.

string domain_name();
  retourne le nom de domaine.

int object_access();
  retourne les droits d'accès de l'objet, une somme des valeurs suivantes :
  // const RIGHTS RIGHT_IS_LOCKED             = 1;
  // const RIGHTS RIGHT_ANYONE_CAN_MOVE       = 2;
  // const RIGHTS RIGHT_ANYONE_CAN_BUY        = 4;
  // const RIGHTS RIGHT_OWNER_CAN_SELL        = 16;
  // const RIGHTS RIGHT_OWNER_CAN_MODIFY      = 32;
  // const RIGHTS RIGHT_NEXT_OWNER_CAN_SELL   = 64;
  // const RIGHTS RIGHT_NEXT_OWNER_CAN_MODIFY = 128;
  // const RIGHTS RIGHT_BUILDER_CAN_TAKE_COPY = 256;
  // const RIGHTS RIGHT_BUILDER_CAN_MODIFY    = 512;

world_position object_world_position (int object_id);
  retourne la position de l'objet sur la planète.

vector object_rotation (int object_id);
  retourne la rotation de l'objet.

int set_object_world_position (int object_id, world_position position);
  déplace l'objet
  renvoie 0 si OK, ou l'une des valeurs négatives suivantes :
         -1 : mauvais object_id
         -2 : pas de droits d'accès de déplacement sur cet objet
         -3 : pas de droits d'accès sur l'area
         -4 : la nouvelle area est pleine

  Vous pouvez déplacer un objet au-dessus de la mer, mais il sera supprimé
  s'il reste 1 heure en mer sans qu'aucun avatar ne le regarde.

  Vous ne pouvez pas déplacer un objet différent de l'objet courant lui-même
  si l'objet script est porté ou a été rezzed par script.

void set_object_rotation (int object_id, vector rotation);
  fait tourner l'objet

int rezz_object_relative (string item_name [, vector         position [, vector rotation]]);
int rezz_object_absolute (string item_name  , world_position position [, vector rotation]);
  rezze un objet dans le monde, soit à une position relative de l'objet parent,
    ou à une position absolue dans le monde.
  renvoie une valeur positive (id de l'objet créé),
    ou une erreur négative (-1 = pas le droit de rezzer, -2 = area pleine)

void wear_object (key avatar, string item_name);
  Faire automatiquement porter un objet à un avatar.
  L'objet est ajouté dans l'inventaire de l'avatar, dans le dossier "Temporary".
  Lorsqu'il est enlevé, l'objet est déplacé dans le dossier "Trash".
  L'avatar ne peut pas modifier ou réutiliser l'objet après cela.

void unwear_object ();
  Enleve l'objet porté.
  Autorisé seulement si le script tourne dans un objet porté.

int parent_object_id ();
  retourne un identifiant positif de l'objet parent qui a rezzé ou porté cet objet,
  ou -1 s'il n'a pas été rezzé ou porté par un script,
  ou -2 si l'id est maintenant invalide parce que l'utilisateur s'est reloggé.
  Cette fonction ne doit être utilisée que lors du premier start car le parent peut rapidement devenir invalide.

void delete_object();
  supprime l'objet exécutant ce script.


Exemples:

  event touch ()
  {
    say ("object id = " + itos(object_id()));
    say ("object name = " + object_name());
    say ("domain name = " + domain_name());
  }

  event touch ()
  {
    world_position wp = object_world_position (object_id());
    say ("world position = " + itos(wp.x) + ","
           + itos(wp.y) + "," + itos(wp.z));
  }

  event touch()
  {
    vector v = object_rotation (object_id());
    say ("rx = " + ftos(v.x));
    say ("ry = " + ftos(v.y));
    say ("rz = " + ftos(v.z));
  }

  event touch()
  {
    say ("au revoir");
    delete_object ();
  }



int next_object_of_area (int area_x, int area_y, ref int snr);
  liste tous les objets de l'area.
  renvoie l'id de l'objet suivant de cette area, ou 0 s'il n'y a plus d'objets.
  snr doit être initialisé à 0 et est changé à chaque appel.
  si l'objet script bouge, la fonction n'est pas fiable.

Exemple:

  event touch()
  {
    int snr = 0;
    for (;;)
    {
      int object_id = next_object_of_area (area_x => 2, area_y => 3, ref snr);
      if (object_id == 0)
        break;

     say (itos(object_id));
    }
  }



Batches de mouvement
====================
Au lieu d'envoyer des commandes individuelles aux objets et aux meshs,
vous pouvez également envoyer une séquence de commandes en batch.

Toutes les commandes d'un batch doivent être entourées par :

  void begin_move ();
  void end_move ();

A l'intérieur d'un batch, vous pouvez spécifier un ou plusieurs jobs, chacun doit commencer par :

  void move_job (bool repeating = false, bool sync = false, int sync_delay = 0);

    repeating   : true pour répéter les commandes.
    sync        : true pour synchroniser avec d'autres objets (pour repeating=true uniquement)
    sync_delay  : une valeur de synchronisation >= 0 en millisecondes (pour sync=true uniquement).

Vous pouvez spécifier une ou plusieurs des commandes suivantes dans un job :

  void set_mesh_active (int mesh_nr, bool enable);
  void set_mesh_position (int mesh_nr, vector position);
  void set_mesh_rotation (int mesh_nr, vector rotation);
  void set_mesh_color (int mesh_nr, int color);
  void set_mesh_transparency (int mesh_nr, float transparency);
  void set_mesh_light (int mesh_nr, int color, float attenuation, float range);
  void set_mesh_lightning (int mesh_nr, bool ambiant, bool sunlight);
  void set_mesh_glow (int mesh_nr, int color);
  void set_mesh_uv (int mesh_nr, int mode, float u = 0.0, float v = 0.0, bool ping_pong = false, bool one_shot = false);
  void set_mesh_texture (int mesh_nr, string texture);
  int set_object_world_position (int object_id, world_position position);
  void set_object_rotation (int object_id, vector rotation);

Entre les commandes, vous pouvez spécifier une durée pour provoquer un fondu enchaîné entre l'état précédent et l'état suivant avec :

  void job_duration (int duration);    // la durée doit être >= 16 millisecondes

Pour arrêter un batch en cours d'exécution, appelez :

  void stop_move ();

Quelques règles :
. si vous spécifiez une commande directe en dehors du batch, le serveur arrêtera d'abord le batch.
. la commande set_object_world_position() ne peut être spécifié que dans le premier job d'un batch.
. un move répétitif doit avoir au moins une commande job_duration.
. les batchs sont exécutés dans l'ordre.
. un batch répétitif ne se répète plus lorsqu'un autre batch est défini.

Autres commandes :

  int end_move2 ();

Au lieu de end_move() qui s'arrête sur une erreur d'area, vous pouvez aussi utiliser end_move2()
qui renvoie 0 si OK ou une erreur négative si l'area ne peut pas être traversée.

 int nb_queued_moves ();

Vous pouvez interroger le nombre de mouvements mis en file d'attente au cas où plusieurs mouvements sans répétion sont en attente.
Notez qu'un maximum de 128 mouvements sont autorisés, après quoi le script s'arrête.


En voici quelques exemples :


Ventilateur tournant
--------------------

  // fan

  bool g_enabled;

  event touch ()
  {
    g_enabled = !g_enabled;

    if (g_enabled)
    {
      begin_move ();

      move_job (repeating => true);
        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 0.0});
        job_duration (1000);
        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 120.0});
        job_duration (1000);
        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 240.0});
        job_duration (1000);

      end_move ();
    }
    else
    {
      stop_move();
    }
  }

  Les angles de rotation doivent être espacés de moins de 180° pour garantir une trajectoire déterministe entre deux angles.


Une porte qui bouge doucement
-----------------------------

  // porte

  bool g_is_open;

  event touch()
  {
    float angle;

    g_is_open = !g_is_open;

    begin_move ();

    move_job (repeating => false);

      job_duration (1000);

      if (g_is_open)
        angle = 90.0;
      else
        angle = 0.0;

      set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, angle});

    end_move ();
  }


Tapis volant
------------

  // Tapis volant

  bool g_on;

  event touch()
  {
    g_on = !g_on;

    if (g_on)
    {
      int id = object_id();
      world_position wp = object_world_position (id);
      world_position wp2 = wp;
      int rc;

      wp2.z += 256*1000;
      wp2.x -= 256*65536;

      begin_move ();

      // first job : change object position between two points
      move_job (repeating => true);
        rc = set_object_world_position (id, wp);
        job_duration (100000);
        rc = set_object_world_position (id, wp2);
        job_duration (100000);

      // second job : some weird rotations
      move_job (repeating => true);
       set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 0.0});
       job_duration (10000);
       set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 20.0, 120.0});
       job_duration (10000);
       set_mesh_rotation (mesh_nr => 1, rotation => {20.0, 0.0, 240.0});
       job_duration (10000);

      end_move ();
    }
    else
    {
      stop_move ();
    }
  }


Objet de couleur pâlissante
 --------------------------

  // fading color object

  event start()
  {
    begin_move ();
    move_job (repeating => true);

      set_mesh_color (mesh_nr => 1,color => 0xFF);
      job_duration (6000);
      set_mesh_color (mesh_nr => 1,color => 0xFF00);
      job_duration (6000);
      set_mesh_color (mesh_nr => 1,color => 0xFF0000);
      job_duration (6000);

    end_move ();
  }


Cube rebondissant
-----------------

  // cube rebondissant qui change de couleur

  event start()
  {
    int i;

    begin_move ();

      // job 1 : position de rebond vers le haut et vers le bas
      move_job (repeating => true);

        for (i=0; i<10; i++)
        {
          float f = itof(i);
          f = 1.0 - f * f * 0.01;
          set_mesh_position (mesh_nr => 1, position => {0.0, 0.0, f});
          job_duration (100);
        }

        for (i=8; i>0; i--)
        {
          float f = itof(i);
          f = 1.0 - f * f * 0.01;
          set_mesh_position (mesh_nr => 1, position => {0.0, 0.0, f});
          job_duration (100);
        }

      // job 2 : modification des angles de rotation
      move_job (repeating => true);

        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 0.0});
        job_duration (1000);
        set_mesh_rotation (mesh_nr => 1, rotation => {30.0, 0.0, 90.0});
        job_duration (1000);
        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 0.0, 180.0});
        job_duration (1000);
        set_mesh_rotation (mesh_nr => 1, rotation => {0.0, 30.0, 270.0});
        job_duration (1000);

      // job 3 : changement de couleur
      move_job (repeating => true);

        set_mesh_color (mesh_nr => 1,color => 0xFF);
        job_duration (2000);
        set_mesh_color (mesh_nr => 1,color => 0xFF00);
        job_duration (2000);
        set_mesh_color (mesh_nr => 1,color => 0xFF0000);
        job_duration (2000);

    end_move ();
  }


Avatar
======

  bool avatar_online (key k);
  Renvoie vrai si un avatar est en ligne, faux sinon.

  string avatar_name (key k);
  Retourne le nom complet d'un avatar (71 caractères maximum).

  int avatar_rank (key k);
  Retourne un rang d'avatar : -1=banned, 0=visitor, 1=resident, 2=member manager,
    3=security officer, 4=senior builder, 5=domain manager, 6=land owner.

  void set_avatar_rank (key k, int rank);
  Change le rang d'un avatar, si vous en avez le droit.

  int avatar_gender (key k);
  Retourne un genre d'avatar : 0=homme, 1=femme.

  int avatar_language (key k);
  Retourne la langue de l'avatar (0 = français, 1 = anglais, 2 = allemand, -1 = key incorrecte)

  int avatar_experience (key k);
  Retourne l'experience de l'avatar, ou -1 si key est inconnue.

  int avatar_timezone (key k);
  Retourne la zone de temps de l'avatar.

  string avatar_title (key k);
  Retourne le titre de l'avatar, maximum 24 caractères.

  world_position avatar_world_position (key k);
  Renvoie une position de l'avatar sur le planète (Z est 0 si debout sur le sol à l'altitude 0).

  int avatar_z_rotation (key k);
  Renvoie une orientation de l'avatar, comme suit :
        0          = nord,  orienté Y positif
       90          = est,   orienté X positive
      -90          = ouest, orienté X negative
      -180 or +180 = sud,   orienté Y négatif


  // Exemple:

  event touch ()
  {
    key            k;
    bool           online;
    string(71)     name;
    int            rank;
    int            gender;
    world_position wp;
    int            angle;

    k = touched_avatar();

    online = avatar_online (k);
    name   = avatar_name (k);
    rank   = avatar_rank (k);
    gender = avatar_gender (k);
    wp     = avatar_world_position (k);
    angle  = avatar_z_rotation (k);

    say ("online = " + btos(online));
    say ("name = " + name);
    say ("rank = " + itos(rank));
    say ("gender = " + itos(gender));
    say ("world pos = " + itos(wp.x) + "," + itos(wp.y) + "," + itos(wp.z));
    say ("angle = " + itos(angle));
  }


Téléportation d'Avatars
-----------------------
  void set_avatar_world_position_and_angle (key            k,
                                            world_position position,
                                            int            angle);
  Téléporte un avatar.


  // Exemple:

  event touch ()
  {
    key            k  = touched_avatar();
    world_position wp = touched_world_position();
    set_avatar_world_position_and_angle (k, position => wp, angle => 0);
  }



key next_avatar (ref int snr);
  liste un à un tous les avatars dans un rayon de 256 mètres.
  snr doit être initialisé à 0, il est changé à chaque appel.
  Si snr vaut 0 après l'appel il ne reste plus d'avatars.
  Cette fonction n'est autorisée que dans les évènements touch, collision, listen, click_avatar ou menu_selected.

Exemple:

  event touch()
  {
    int snr = 0;
    for (;;)
    {
      key avatar = next_avatar (ref snr);
      if (snr == 0)
        break;

      say (avatar_name (avatar));
    }
  }



S'asseoir, animations
=====================
bool is_sitting (key avatar);
  Teste si un avatar est assis sur cet objet.

bool sit (int mesh_nr, vector position, vector rotation, key avatar);
  Assied un avatar avec position/rotation sur le nr de mesh de cet objet.
  Ceci annule tout sit précédent et annule toutes les animations précédentes.
  Le script doit s'exécuter sur le même domaine que l'avatar, sinon il renvoie faux.

void unsit (key avatar);
  Fait qu'un avatar se lève s'il était assis sur cet objet
  et arrête toutes les animations qui ont été lancées par cet objet.

void start_animation (string animation, key avatar);
void stop_animation (string animation, key avatar);
  Démarre ou arrête une animation.
  Une animation BVH doit être présente dans le dossier Scripts de l'objet.

bool is_animation_active (string animation, key avatar);
  Teste si cette animation est actuellement active sur l'avatar donné.

void override_animation (int typ, string animation);
  remplace les animations standard (se tenir debout, marcher, courir, voler)
  uniquement pour un objet porté.
  typ : 0=stand, 1=walk, 2=fun, 3=fly
  utilisez un string vide pour annuler le remplacement.


// Exemple 1 : sphère de danse

  const string ANIMATION_NAME = "dancing";

  event touch()
  {
    key k = touched_avatar();

    if (is_animation_active (ANIMATION_NAME, k))
      stop_animation (ANIMATION_NAME, k);
    else
      start_animation (ANIMATION_NAME, k);
  }


// Exemple 2 : s'asseoir sur une chaise

  event touch()
  {
    key k = touched_avatar();

    if (is_sitting (k))
    {
      unsit (k);
    }
    else if (sit (mesh_nr  => 1,
                  position => {0.0, 0.0, 1.0},
                  rotation => {0.0, 0.0, 0.0},
                  avatar   => k))
    {
      start_animation ("sit", k);
    }
  }


Event Click_Avatar
------------------

  event click_avatar()
  {
    key k1 = clicking_avatar();   // obtenir la clé de l'avatar qui clique
    key k2 = clicked_avatar();    // obtenir la clé de l'avatar qui est cliqué.

    say ("click " + avatar_name(k1)
                  + " clicked on "
                  + avatar_name(k2));
  }

Event click_avatar() est généré lorsque l'utilisateur clique sur un avatar
qui est assis sur un objet. Tous les scripts de cet objet reçoivent
alors cet événement. Ceci peut être utilisé pour changer l'animation de l'avatar.

Les fonctions suivantes sont autorisées dans un événement click_avatar :

  key clicking_avatar();   // obtenir la clé de l'avatar qui clique
  key clicked_avatar();    // obtenir la clé de l'avatar qui est cliqué.


Avatars Assis
-------------

Tous les avatars assis sur un objet peuvent être listés comme ceci :


  sitter s;

  while (get_sitter (out s))
  {
    say ("sitter : " + avatar_name(s.avatar));
    say ("mesh_nr : " + itos(s.mesh_nr));
    say ("pos : " + ftos(s.position.x)
            + " " + ftos(s.position.y)
            + " " + ftos(s.position.z));
  }


La structure sitter est définie comme suit :

  struct sitter
  {
    key    avatar;
    int    mesh_nr;
    vector position;
    vector rotation;
  }


Ceci peut être utilisé par exemple pour des animations de couple :


  event touch()
  {
    key k = touched_avatar();

    if (is_sitting (k))   // déjà assis
    {
      unsit (k);    // se lever
    }
    else
    {
      sitter s;
      if (get_sitter(out s) && s.mesh_nr == 1)
      {
        // quelqu'un est déjà assis sur le mesh 1
        if (sit (mesh_nr  => 2,   // s'asseoir sur mesh 2
                      position => {0.0, 0.0, 1.0},
                      rotation => {0.0, 0.0, 0.0},
                      avatar   => k))
        {
          start_animation ("sit", k);
        }
      }
      else
      {
        if (sit (mesh_nr  => 1,   // s'asseoir sur mesh 1
                      position => {1.0, 0.0, 1.0},
                      rotation => {0.0, 0.0, 0.0},
                      avatar   => k))
        {
          start_animation ("sit", k);
        }
      }
    }
  }



Menus
=====

void display_menu (key avatar, string menu [,string menu2[,string menu3[,string menu4, ..]]]);
  Affiche un menu utilisateur.
  Le menu peut avoir max 3 niveaux, max 20 lignes dans chaque niveau.
  Si le menu est plus long que 1024 caractères, coupez le en plusieurs parties.
  Quand un utilisateur sélectionne un menu, le script reçoit un évènement menu_selected.


Exemple:

  event touch ()
  {
    key k = touched_avatar();
    display_menu (k, "On:1,Off:0,Color:[red:0xFF,green:0xFF00,blue:0xFF0000]");
  }

  event menu_selected (key avatar, int menu_id)
  {
    say ("avatar " + avatar_name(avatar) + " a choisit le menu " + itos(menu_id));
  }


Inventaire
==========

void give_inventory (string item_name);
  donne l'item de nom donné à l'inventaire de l'utilisateur
  cette fonction n'est autorisée que dans les évènements TOUCH, MENU_SELECTED and COLLISION.

string item_name (string previous_name);
  liste tous les items du dossier script de l'objet.
  renvoie le nom de l'item suivant, ou "" s'il n'y en a pas d'autre.

string item_type (string item_name);
  renvoie le type d'un item
  renvoie l'une des valeurs "TEX", "OBJ", "SCR", "BVH", "SHP", "WAV"
                         ou "" si item_name n'existe pas.


Exemple:

  // donne tous les items de l'objet sauf ceux de type script
  event touch()
  {
    string(32) name;
    clear name;
    for (;;)
    {
      name = item_name (previous_name => name);
      if (name == "")
        break;
      if (item_type (name) != "SCR")
      {
        give_inventory (item_name => name);
        say ("donne " + name);
      }
    }
  }




Blocages
========

a) Blocages à partir d'objets dans le monde
-------------------------------------------
Les blocages peuvent être appliqués aux avatars qui se trouvent dans un espace en forme de boîte autour d'un objet rezzé.

  struct space
  {
    vector min, max;
  }

  // Appliquer des blocages à un avatar.
  // L'avatar doit être dans le même domaine que l'objet.
  // Si le paramètre avatar est vide, la commande s'applique à tous les avatars
  //   qui sont à l'intérieur de l'espace.
  // options:
  //   CAPTIVE   :  0x0001 signifie que l'avatar ne peut pas quitter l'espace de la boîte
  //   FLY       :  0x0002 signifie que l'avatar ne peut pas se téléporter
  //   INVENTORY :  0x0008 bloque l'inventaire
  //   NAMES     :  0x0010 cache les noms d'avatars dans People et Conversation, et bloque les profils sauf le sien
  //   TELEPORT  :  0x0020 signifie que l'avatar ne peut pas se téléporter
  //   CAMERA    :  0x0200 signifie que l'avatar ne peut pas déplacer la caméra à l'extérieur de la boîte.
  //   TOUCH     :  0x0400 signifie que l'avatar ne peut pas toucher les objets en dehors de l'espace de la boîte.
  //   RADAR     :  0x0800 signifie que l'avatar ne peut pas voir les gens dans People
  //   plusieurs options peuvent être additionnées.
  //   0 signifie aucun blocage.
  //   toute recompilation de script ou erreur de script dans l'objet supprime également tous les blocages.
  // l'espace peut être aussi grand que 512m x 512m (-256.0 to +256.0)
  void block_avatar_options (key avatar, int options, space space);

  // Récupérer les options de blocage d'avatar
  int avatar_block_options (key avatar);

  // Récupérer le prochain avatar ayant des blocages.
  // Effacer l'avatar au premier appel, la clé vide retournée signifie qu'aucun autre avatar n'est bloqué.
  key next_avatar_blocked (key avatar);

Exemple:

  event touch()
  {
    key k;
    clear k;
    block_avatar_options (avatar  => k,
                          options => 0x0001 + 0x0400,
                          space   => {min => {-5.0, -4.0, 0.0},
                                      max => {+5.0,  4.0, 4.0}});
  }


b) Blocages à partir d'objets portés
------------------------------------

void block_worn_object (blocking_parameters parameters);
  Bloquer certaines fonctions de l'avatar.
  Autorisé uniquement pour un objet porté.

struct blocking_parameters
{
  int   options;
  float walking_speed;    // en mètres. si moins de 3.2 m/s alors courir est bloqué aussi.
  float camera_distance;  // en mètres (si 0.0 l'avatar est invisible pour moi)
  float touch_distance;   // en mètres.
  float radar_distance;   // en mètres. 0.0 à 256.0
  uint  fog_setting;      // 3 bytes du bas = couleur brouillard, byte du haut = niveau de brouilland de 0 à 15.
}

// option values:
// 0x0001 : bloque les menus 'unwear' et 'properties' de l'objet porté.
// 0x0002 : bloque voler
// 0x0004 : bloque les menus 'wear'/'unwear' de skins et autres textures de vêtements
// 0x0008 : bloque l'inventaire
// 0x0010 : cache les noms d'avatars dans People et Conversation, et bloque les profils sauf le sien
// 0x0020 : bloque la téléportation
// 0x0040 : bloque l'écriture sur le chat (sauf pour les event listen d'objets portés)
// 0x0080 : bloque la réception sur le chat (sauf depuis des commandes say/say_to d'objets portés)
// 0x0100 : limite la vitesse de la marche, voir .walking_speed
// 0x0200 : limite la distance de la caméra, voir .camera_distance
// 0x0400 : limite la distance de toucher par click gauche, voir .touch_distance
// 0x0800 : limite la distance à laquelle les avatars sont vus sur People, voir .radar_distance
// 0x8000 : active le brouillard, voir .fog_setting

Un avatar qui est bloqué peut cliquer sur le bouton CheatOut dans le profil pour effacer tous les blocages,
mais il est ensuite ajouté dans la liste des Tricheurs dans les informations du domaine.


Fichiers Texte
==============
Des fichiers texte peuvent être ajoutés dans les scripts et lus ligne par ligne.

  // compte le nombre de lignes d'un fichier texte
  int count_lines (string item);

  // retourne la ligne n d'un fichier texte
  string read_line (string item, int line);

Exemple:

  // lire toutes les lignes d'un fichier texte
  event start()
  {
    int count = count_lines ("mytext");
    int i;
    for (i=1; i<=count; i++)
    {
      string(128) s;
      s = read_line ("mytext", i);
      say (s);
    }
  }

Données permanentes
===================

a) stockage pour des objets dans le monde
-----------------------------------------

void store (string index, string value);    //  insérer ou mettre à jour la valeur associée à index

  store() est utilisé pour sauvegarder une chaîne de caractères
  sur un serveur de stockage permanent lié à l'identifiant de l'objet.

  Vous pouvez stocker un maximum de 10.000 chaînes de caractères,
  après quoi vous obtenez une erreur de script.

  Les chaînes ne sont pas effacées au redémarrage du script,
  la seule façon de le faire est de supprimer l'objet et d'en créer un nouveau.
  Vous pouvez supprimer une valeur de chaîne individuelle en stockant une chaîne vide.
  La chaine index ne doit pas dépasser 50 caractères et ne doit pas contenir des caractères nuls.

string fetch (string index);                // récupérer

  fetch() est utilisé pour récupérer une valeur précédemment sauvegardée avec store().
  S'il n'y en avait pas, une chaîne vide est retournée.

Exemple:

  event start()
  {
    store (index => "hi-score", value => " 10 ");
    say (fetch(index => "hi-score"));   // va dire 10
  }


b) stockage pour des objets portés
----------------------------------

Des données permanentes peuvent être stockées dans l'inventaire de l'utilisateur,
même si l'utilisateur se reconnecte ou si l'objet est enlevé et porté à nouveau.

void save_data_to_inventory (string index, string value);

  stocke les données dans l'inventaire sur le PC client
  . pour objet porté uniquement
  . index doit avoir un maximum de 50 caractères et ne doit pas contenir des caractères nuls.
  . une chaîne vide comme valeur supprime l'enregistrement.
  . vous pouvez stocker un maximum de 10_000 enregistrements,
    les autres enregistrements sont ignorés silencieusement.

void load_data_from_inventory (string index);

  load data from inventory on client pc
  . for worn object only
  . value is returned in the following event :

    event inventory_data_arrived (string index, string value)
    {
      say ("index = '" + index + "'");
      say ("value = '" + value + "'");
    }



Particules
==========

La commande generate_particles() crée un pulvérisateur de particules au centre d'un mesh.

  void generate_particles (particule_parameters p);


Exemple:

  event start ()
  {
    particule_parameters p;

    clear p;

    p.mesh_nr      = 1;

    p.nb_particles = 10;
    p.pause        = 1000;

    // sprayer
    p.direction_angle = {-180.0, +180.0};
    p.height_angle    = {0.0, 0.0};
    p.radius          = 0.5;

    p.life[0].durations   = {15_000, 15_000};    // 15 secondes
    p.life[0].begin_speed = {1.0, 1.0};          // 1 m/s
    p.life[0].end_speed   = {1.0, 1.0};

    p.life[0].begin_color = {0xFFFFFFFF, 0xFFFFFFFF};  // blanc, 0% transparent
    p.life[0].end_color   = {0xFFFFFFFF, 0xFFFFFFFF};

    p.life[0].begin_size  = {{0.2, 0.2}, {0.2, 0.2}};   // taille 0.2 x 0.2 m
    p.life[0].end_size    = {{0.2, 0.2}, {0.2, 0.2}};

    p.life[0].orientation = 0;     // toujours orienté verticalement

    p.ambiant = true;
    p.sunlight = true;

//    p.texture = "brilliant";   // nécessite une texture appelée "brillant" dans le dossier "scripts"

    generate_particles (p);
  }


La structure particule_parameters contient les zones suivantes :

struct particule_parameters
{
  int         mesh_nr;              // nr mesh où l'émetteur est créé

  // rafales
  int         nb_particles;         // nombre de particules émises par rafale
  int         pause;                // temps de pause entre rafales, en millisecondes
  int         nb_bursts;            // nombre de rafales, 0 signifie infini

  // naissance de particules dans une boîte
  vector[2]   box;                  // les particules sont générées à une position aléatoire à l'intérieur de la boîte

  // naissance de particules dans le pulvérisateur
  float[2]    direction_angle;      // pulvériser vers l'extérieur dans la plage d'angle horizontal
  float[2]    height_angle;         // pulvériser vers l'extérieur dans la plage d'angle vertical
  float       radius;               // distance de pulvérisation à partir du centre où les particules sont créées

  // Particule 3 durées de vie
  lifetime    life[3];              // 3 vies successives, voir ci-dessous.

  bool        dont_follow_emitter;  // true = si le mesh émetteur bouge ou tourne, les particules ne suivent pas.

  bool        ambiant;              // true = les particules reçoivent la lumière ambiante
  bool        sunlight;             // true = les particules reçoivent la lumière du soleil

  int         shininess;            // 0 .. 4  0=éteint, 1 to 4 intensité du reflet
  int         shinysize;            // 0 .. 7  0=pas de tache, 1 to 7 taille de la tache

  int         emissive_color;       // couleur luminescente

  string(32)  texture;              // nom de la texture de la particule, doit être ajouté dans le dossier scripts

  int         mode_uv;              // idem que mesh u, v
  float       u;
  float       v;

  bool        sort;                 // trier les particules (meilleur résultat pour textures transparentes mais utilise du CPU !)

  // mode chaine
  int       leash_id;       // id de l'objet à relier par la chaîne (non-zero active le mode chaine)
  int       leash_mesh_nr;  // numéro de mesh de l'objet distant où attacher la chaîne (1..32)
  float     leash_length;   // longueur de chaine en mètres (maximum 256)
  float     leash_stretch;  // facteur d'allongement (0..1) de sorte que les particules se chevauchent un peu à la longueur maximale (0.0 = aucun, 0.2 = anneaux de chaîne)
  bool      leash_physics;  // true = tire l'avatar vers l'arrière s'il est plus éloigné que la longueur de chaine
}


Les particules peuvent avoir un maximum de 3 vies au cours desquelles elles ont un comportement différent.

La structure lifetime comprend les zones ci-après.

Lorsqu'il y a deux zones, vous pouvez spécifier une limite inférieure et une limite supérieure,
et une valeur aléatoire entre les deux limites est sélectionnée pour chaque particule.

struct lifetime
{
  int[2]        durations;           // durée de vie des particules, en msecs (max 1 jour)
  float[2]      begin_speed;         // Début de la plage de vitesse du pulvérisateur
  float[2]      end_speed;           // Fin de la plage de vitesse du pulvérisateur
  vector[2]     begin_velocity;      // Vitesse de début supplémentaire en m/s
  vector[2]     end_velocity;        // Vitesse de fin supplémentaire en m/s
  vector[2]     begin_acceleration;  // accélération de début supplémentaire en m/s2
  vector[2]     end_acceleration;    // accélération de fin supplémentaire en m/s2
  vector[2]     begin_size;          // début taille des particules (largeur, hauteur) en mètres
  vector[2]     end_size;            // fin taille des particules (largeur, hauteur) en mètres
  int[2]        begin_color;         // début couleur et transparence
  int[2]        end_color;           // fin couleur et transparence
  int           orientation;         // 0=vertical, 1=vers la vitesse, 2=horizontal, 3=chaîne.
}


Pour arrêter les particules, mettez p.mesh_nr ou p.nb_particles à zéro.

Exemple:

  event start ()
  {
    particule_parameters p;
    clear p;
    generate_particles (p);
  }


Sound
=====

Jouer un son
------------
  void play_sound (string item_name,
                   float  volume = 1.0,     // 0.0 à 1.0
                   float  radius = 20.0);   // 0 à 1024 m

Les fichiers son doivent être des .wav 44.1KHz PCM 16-bit maximum 90 secondes ou bien ils sont coupés.
Un maximum de 8 sons peuvent être démarrés en même temps, au-delà ils sont ignorés.

Exemples:
  play_sound ("ding");
  play_sound ("ding", volume => 1.0);
  play_sound ("ding", volume => 1.0, radius => 20.0);


Jouer un son en boucle
----------------------
  void start_ambiant_sound (string item_name,
                            float  volume = 1.0,     // 0.0 à 1.0
                            float  radius = 20.0);   // 0 à 1024 m

Les fichiers son doivent être des .wav 44.1KHz PCM 16-bit maximum 90 secondes ou bien ils sont coupés.
Seul un son d'ambiance par objet est autorisé, les sons d'ambiance précédents sont annulés.

Exemples:
  start_ambiant_sound ("sea");
  start_ambiant_sound ("sea", volume => 1.0);
  start_ambiant_sound ("sea", volume => 1.0, radius => 20.0);


Arrêter le son d'ambiance
-------------------------

  void stop_ambiant_sound ();


Media
=====

Jouer un média
--------------
  void media_play (key avatar, string url);

Joue un fichier ou stream multimédia (mp3, mp4, wav, ..)
Un url vide ou illegal va stopper le média.
Un url identique à celui joué actuellement n'a pas d'effet.
Pour un média vidéo, vous devez construire un écran mesh rectangulaire de ratio longueur=4 hauteur=3,
désactiver ambiant et sunlight, régler color et glow à 255,255,255,
et ensuite aller dans le menu "mesh / various" et cocher l'option 'video'.

Exemple:

  event touch()
  {
    key k = touched_avatar();
    media_play (k, "http://dino.com/tina.mp4");
  }


Mettre un média en pause
------------------------
  void media_pause (key avatar, bool on);

Mettre un média en pause ou le redémarrer.

Exemples:
  media_pause (k, on => true);   // pause
  media_pause (k, on => false);  // redémarre


Changer la position d'un média
------------------------------
  void media_seek (key avatar, int mode, float seconds);

Changer la position d'un média
  . mode 0 : position absolue en secondes
  . mode 1 : position relative en secondes (secondes peuvent être négatives)
  . mode 2 : position relative depuis la fin (secondes doivent être negatives)

Exemple:
  media_seek (k, mode => 1, seconds => -5.0);  // revenir 5 secs en arrière


Changer le volume du média
--------------------------
  void media_volume (key avatar, float volume);   // 0.0 to 1.0

Changer le volume du média
Ceci change également la valeur dans Outils/Sons

Exemple:
   media_volume (k, volume => 0.5);  // volume 50%


Appels Tcpip
============
Vous pouvez échanger des chaînes UTF-16 de 1024 caractères maximum avec un serveur tcp/ip externe
en utilisant les commandes suivantes :

  void tcp_open (string ip, int port);
  void tcp_close ();
  void tcp_send (string message);

et ces évènements :

  event tcp_received (string message)
  event tcp_disconnected ()

Les chaines sont envoyées avec une entête longueur de 2 bytes.
Vous ne pouvez pas envoyer plus d'une chaine par seconde.
En cas d'event server_restart(), la connexion est perdue et doit être réouverte.


Vous pouvez obtenir le nom d'hôte du serveur planete en utilisant :

  string server_name ();  // max 256 caractères



Glisser-déposer
===============
Avec la souris, vous pouvez glisser et déposer des images de votre disque dur
pour les afficher sur un objet dans le monde.

Exemple:

  event image_dropped ()
  {
    set_mesh_texture (1, "");  // appliquer l'image sur le mesh 1
  }

L'affichage doit avoir un format 4/3 (largeur = 4, hauteur = 3).
Les images seront automatiquement redimensionnées et centrées avec un bord transparent.

La commande set_mesh_texture(mesh_nr, "") ; aura un effet uniquement :
. pour les objets dans le monde (pas les attachments),
. pour les commandes, (pas dans un job),
. à l'intérieur d'un évènement image_dropped seulement.
Dans tous les autres cas, il restaure la texture originale.

A l'intérieur d'un événement image_dropped, les appels suivants sont autorisés :

  key            touched_avatar ();          // qui a glissé l'image
  int            touched_mesh_nr ();         // sur quel numéro de mesh
  world_position touched_world_position ();  // à quelle position dans le monde
  vector         touched_mesh_position ();   // à quelle position sur le mesh



Conversions
===========
  string itos (int    value, int width=0, string filler=" ");      // exemple: itos(23, 5, "0") == "00023"
  string ftos (float  value, int width=0, int decimals = 3);       // exemple: ftos(23.2, 5) == " 23.2"
  string btos (bool   value, int width=0);                         // exemple: btos(b) == "true"
  bool   stob (string str);                                        // exemple: stob(" true ") == true
  int    stoi (string str);                                        // exemple: stoi("-23") == -23
  float  stof (sring  str);                                        // exemple: stof(" 13.7 ") == 13.699
  float  itof (int    value);
  int    ftoi (float  value);                                      // tronque

Manipulation de Strings
=======================
  int    len   (string value);                                     // exemple: len("abc") == 3
  string chr   (int c1, int c2, int c3, ..., int c16);             // exemple: chr(65,66,67) == "ABC"
  int    asc   (string value, int index=1);                        // exemple: asc("AB") == 65    asc("ABC",2) == 66
  string left  (string value, int count);                          // exemple: left("ABCD",2) == "AB"
  string right (string value, int count);                          // exemple: right("ABCD",2) == "CD"
  string mid   (string value, int index, int count=<ALL>);         // exemple: mid("ABCDEF",2,3) == "BCD"   mid("ABCDEF",5) == "EF"
  int    pos   (string phrase, string word);                       // exemple: pos("ABCDEF","CD") == 3    pos("ABCDEF","X") == 0
  string dup   (string value, int count);                          // exemple: dup("-*",3) == "-*-*-*"
  string upper (string value);                                     // enlève les accents et converti en majuscules
  string lower (string value);                                     // enlève les accents et converti en minuscules
  string trim  (string value);                                     // enlève les espaces avant et après
  string ltrim (string value);                                     // enlève les espaces avant
  string rtrim (string value);                                     // enlève les espaces après
  string resolve_icons (string value);                             // converti les séquences comme :) en codes icônes

Calendar
========
  struct date_time
  {
    int  year;     /* 1901 to 9999 */
    int  month;    /*    1 to   12 */
    int  day;      /*    1 to   31 */
    int  hour;     /*    0 to   23 */
    int  min;      /*    0 to   59 */
    int  sec;      /*    0 to   59 */
  }

  date_time now ();                                                // heure gmt
  int       weekday            (date_time date);                   // (1=lundi, 7=dimanche)
  date_time add_seconds        (date_time date, int seconds);
  int       area_time_offset   ();                                 // secondes à ajouter au temps pour obtenir l'heure locale de l'area
  int       nb_days_since_1901 (date_time date);                   // nb jours entre le 1/1/1901 et la date

Math
====
  int       abs   (int value);
  int       min   (int a, int b, int c, .., int h);
  int       max   (int a, int b, int c, .., int h);
  int       rnd   (int a, int b);

  float     frnd  ();                                              // valeur comprise entre 0 inclus et 1 exclu
  float     fabs  (float value);

  float     sin   (float angle);                                   // angle en degrés
  float     cos   (float angle);                                   // angle en degrés
  float     atan2 (float y, float x);                              // angle en degrés

  float     sqrt  (float angle);
  float     trunc (float angle);
  float     round (float angle);
  float     fmin  (float a, float b, float c, .., float h);
  float     fmax  (float a, float b, float c, .., float h);


Quelques exemples
=================

Un script de porte simple
-------------------------

  // script de porte

  bool g_is_open;

  event touch ()
  {
    float angle;

    g_is_open = !g_is_open;

    if (g_is_open)
      angle = 120.0;
    else
      angle = 0.0;

    set_mesh_rotation (mesh_nr => 1,  rotation => {0.0, 0.0, angle});
  }


Un script de porte avec fermeture après 10 secondes
---------------------------------------------------

  // Un script de porte avec fermeture après 10 secondes

  bool g_is_open;

  event touch ()
  {
    float angle;

    g_is_open = !g_is_open;

    if (g_is_open)
      angle = 120.0;
    else
      angle = 0.0;

    set_mesh_rotation (mesh_nr => 1,  rotation => {0.0, 0.0, angle});

    start_timer (nr => 0, seconds => 10.0);
  }

  event timer (int nr)
  {
    set_mesh_rotation (mesh_nr => 1,  rotation => {0.0, 0.0, 0.0});
    g_is_open = false;
  }


Interrupteur de lampe
---------------------

  // lamp script

  bool g_is_enabled;

  event touch ()
  {
    float range;

    g_is_enabled = !g_is_enabled;

    if (g_is_enabled)
      range = 2.0;
    else
      range = 0.0;

    set_mesh_light (mesh_nr => 1, color => 0xFFFFFF, attenuation => 0.6, range => range);
  }


Coût des Scripts
================
Le coût du script dépend du nombre d'instructions, de la taille des variables globales
et du stockage pour les chaînes de caractères. Les variables locales ne sont pas incluses.

Bugs
====
En cas de bug, envoyez un descriptif à : marcsamu@hotmail.com


<<<First<<prev.>next.>>>Last>RepReply^Discussion ^vDiscussion vDelDelete the discussion