mardi 29 janvier 2008

llPlaySound


Le lsl permet aussi de jouer du son, c'est ce que fais la fonction du jour, Nous allons essayer de rentrer dans une thématique musical.
 llPlaySound prend deux paramètres, un string qui est le nom du son et un float qui est le volume, le son varie de 0 à 1.
Notre programme permet de lire le premier son de l'inventaire quand on lance notre programme


default
{
    state_entry()
    {
        //recupère le premier son de l'iventaire
        string son=llGetInventoryName(INVENTORY_SOUND,0);

        //la fonction du jour
        llPlaySound(son,0.8);
    }

}

jeudi 24 janvier 2008

llListenControl


llListenControl permet d'activer ou de desactiver l'ecoute d'un channel, on avait déjà vu que ce système etait possible avec llRemoveListen.
Cette fonction présente un gros interet voir une nécéssité quand on ecoute le channel publique. Tout simple parcequ'il y a enorment de message qui passe sur ce channel donc beaucoup de travail pour le script.
Les listen sur le channel public font énormement laguer; Il faut bien comprendre qu'il ne sert à rien d'ecouter un channel pour rien.
Donc soit on le remove car on en a besoin qu'une fois soit control si c'est répétitif mais temporaire.
La fonction prends deux paramètres:
Un integer qui permet d'identifier le listen cette valeur nous est retourné par llListen
et un True/False pour arreter ou relancer l'ecoute

integer KeyListen;

default {
    state_entry()
    {
        // ecoute le channel public
        KeyListen = llListen(PUBLIC_CHANNEL, "", NULL_KEY, "");
    }

    touch_start(integer total_number)
    {
        // la fonction du jour
        llListenControl(KeyListen, TRUE);
    }
   
    listen(integer channel, string name, key id, string message)
    {
        if (message == "off")
            llListenControl(KeyListen, FALSE);
        else
        //affiche en float text le contenu du chat public
            llSetText(message,<1.0,1.0,1.0>,1.0);        
    }
}

mercredi 23 janvier 2008

llEmail


llEmail comme vous pouvez vous en douter permet d'envoyer des mails. Sur Second Life cette technique est très simple.
IL suffit de fournir à la fonction, adresse, sujet, message. L'exemple d'aujourd'hui permet d'envoyer qui et combien a donné de Tips

default
{
    state_entry()
    {
        llSetPayPrice(PAY_HIDE,[50,100,200,500]);
    }
    money(key giver, integer amount)
    {
        string adresse="lancelot.joubert@gmail.com";
        string sujet=llGetObjectName();
        string message=llKey2Name(giver) + " " + (string)amount;
       llEmail(adresse,sujet ,message);    
    }
}

mardi 22 janvier 2008

llMapDestination


llMapDestination pemet de faire un téléport longue portée d'une simà une autre via l'interface de choix de destination.
Ainsi, vous pourrez dans une autre sim  faire une pub qui vous emmène dans votre magsin en clickant dessus.
La fonction prend trois paramètres, tout d'abord un string qui est le nom de la sim destination,
un vecteur determinant la position dans la sim, puis aussi une rotation, mais ce n'est que accessoire....


string sim_name;
vector pos;
default
{
    touch_start(integer total_number)
    {
        llMapDestination(sim_name, pos, ZERO_VECTOR);
    }
}

vendredi 18 janvier 2008

State


Aujourd'hui il ne s'agira pas d'une fonction, mais comment bien utilisé "state" ou etat.  Dans notre exemple allons frabriquer un pseudo feu rouge.
Chaque evenement est spécifique à l'etat dans lequel on est ainsi, on peut avoir le même evenement dans fifferent etat et qu'il ne fasse pas la même chose.
Décomposons le programme, je commence dans l'etat default, l'etat de base est l'etat rouge, alors on "saute" dedans.
On mets à rouge noter objet et au bout de 5 secondes, il passe à vert, puis après 5 seconde il passe à l'orange pour seulement 3 secondes.
Il y a biensure une technique pour le faire sans les états mais c'est beaucoup plus compliqué et surtout moins lisible.
Car il aurait fallu faire plein de tests imbriqués, perdant ainsi en clarté de lecture.
Pour savoir quand utilisé les state c'est simple, plus vous avez de conditions dans un seul et même evenement, il serait peut être judicieux de l'utiliser.

default
{
    state_entry()
    {
       state rouge;
    }
}
state rouge
{
    state_entry()
    {
        llSetColor(<1.0,0.0,0.0>,ALL_SIDES);
        llSetTimerEvent(5);
    }
    timer()
    {
        state vert;
    }
}
state orange
{
    state_entry()
    {
        llSetColor(<1.0,1.0,0.0>,ALL_SIDES);
        llSetTimerEvent(3);
    }
    timer()
    {
        state rouge;
    }
}
state vert
{
    state_entry()
    {
        llSetColor(<0.0,1.0,0.0>,ALL_SIDES);
        llSetTimerEvent(5);
    }
    timer()
    {
        state orange;
    }
}

mercredi 16 janvier 2008

llStopAnimation

Avec cette fonction, nous avons enfin tout pour faire une pose ball rudimentaire. La fonction du jour permet d'arrêter une animation de l'avatar. Quand on fait un sit sur un objet, par défaut cela lance l'animation "sit" (logique). Notre pose ball est déstiné à mettre notre avatar allongé, donc il faut arrêter cette position assise avant de lancer notre position allongée.
llStopAnimation a le même fonctionnement que llStartAnimation pour ses paramètres mais une démarre l'animation et l'autre l'arrête.
Il y a une imperfection dans cette pose ball mais vous trouverez laquelle, la solution se cache dans llSitTarget
Bonne chance et bonne animation

default
{
state_entry()
{
// change le libellé de sit
llSetSitText("Dormir");
}

// l'evenement se produit d'un changement avec un prim
// dans le cas qui nous interesse je m'assieds ou je me lève
changed(integer change)
{
// verifie si il s'agit d'un changement de liaison
if(change==CHANGED_LINK)
{
// la fonction du jour
key user=llAvatarOnSitTarget();

// on verifie la presence de l'avatar
if(user!=NULL_KEY)
{
// arrete l'animation naturelle de sit
llStopAnimation("sit");

// démare l'animation sleep pour mettre l'avatar allonger
llStartAnimation("sleep");
}
else
{
// arretes l'animation quand l'avatar se lève
llStopAnimation("sleep");
}

}
}
}

mardi 15 janvier 2008

llStartAnimation

La fonction du jour permet de lancer une animation. Cette fonction nécéssite que l'avatar ait repondu oui à la demande de permission sinon le script fais une erreur.
C'est pour cela que l'on teste si la permission est égal à animation. La fonction prend en paramètre une chaine de caractères correspondant à l'animation.
Cette valeur peut être une animation contenue dans votre objet, soit une des animations déjà existante nativement les "Built In"


aim_l_bow
aim_r_bazooka
aim_r_handgun
aim_r_rifle
angry_fingerwag
angry_tantrum
away
backflip
blowkiss
bow
brush
busy
clap
courtbow
crouch
crouchwalk
dance1
dance2
dance3
dance4
dance5
dance6
dance7
dance8
dead
drink

express_afraid
express_afraid_emote
express_anger
express_anger_emote
express_bored
express_bored_emote
express_cry
express_cry_emote
express_disdain
express_embarrassed_emote
express_frown
express_kiss
express_laugh
express_laugh_emote
express_open_mouth
express_repulsed
express_repulsed_emote
express_sad
express_sad_emote
express_shrug
express_shrug_emote
express_smile
express_surprise
express_surprise_emote
express_tongue_out
express_toothsmile
express_wink
express_wink_emote
express_worry
express_worry_emote

falldown
female_walk
fist_pump
fly
flyslow
hello
hold_l_bow
hold_r_bazooka
hold_r_handgun
hold_r_rifle
hold_throw_r
hover
hover_down
hover_up
impatient
jump
jumpforjoy
kick_roundhouse_r
kissmybutt
land
laugh_short
motorcycle_sit
musclebeach

no_head
no_unhappy
nyanya
peace
point_me
point_you
prejump
punch_l
punch_onetwo
punch_r
rps_countdown
rps_paper
rps_rock
rps_scissors
run
salute
shoot_l_bow
shout
sit
sit_female
sit_generic
sit_ground
sit_to_stand
sleep
smoke_idle
smoke_inhale
smoke_throw_down

snapshot
soft_land
stand
stand_1
stand_2
stand_3
stand_4
standup
stretch
stride
surf
sword_strike_r
talk
throw_r
tryon_shirt
turn_180
turnback_180
turnleft
turnright
type
walk
whisper
whistle
wink_hollywood
yes_happy
yes_head
yoga_float




default
{
state_entry()
{
// affiche le texte au dessus de l'objet
llSetText("Touchez moi pour danser",<1.0,1.0,1.0>,1.0);
}

touch_start(integer total_number)
{
// demande la permission d'animer l'avatar
llRequestPermissions(llDetectedKey(0),PERMISSION_TRIGGER_ANIMATION);
}

// se produit apres une demande permission
run_time_permissions(integer permissions)
{
// verifie que la réponse est oui pour l'animation
if(permissions==PERMISSION_TRIGGER_ANIMATION)
{
// la fonction du jour
llStartAnimation("dance1");
}
}
}

lundi 14 janvier 2008

llSetSitText


La fonction du jour est relativement basique. Vous avez déjà certainement vu sur les camp ou les teleport que le nom où est marqué sit a été changé.
Grace à llSetSitText vous pouvez changer le nom du menu. Cela permet de s'adapter au contexte.
Juste un paramètre, le nom que vous voulez mettre

default
{
    state_entry()
    {
        // position de destination x,y,z
        vector Destination=<512,34,10>;

        // distance relative au teleport
        vector offset=(Destination-llGetPos())/llGetRot();

        // determine la position d'arriver
        llSitTarget(offset,ZERO_ROTATION);

        // la fonction du jour
        llSetSitText("Teleport");
    }
    // l'evenement se produit d'un changement avec un prim
    // dans le cas qui nous interesse je m'assieds ou je me lève
    changed(integer change)
    {
        // verifie si il s'agit d'un changement de liaison
        if(change==CHANGED_LINK)
        {
            // la fonction du jour
            key user=llAvatarOnSitTarget();

            // on verifie la presence de l'avatar
            if(user!=NULL_KEY)
                // remet debout l'avatar à la destination
                // sinon il arrive en position assise
                llUnSit(user);
        }
    }
}

vendredi 11 janvier 2008

llSitTarget


La fonction du jour llSitTarget détermine la position de l'avatar après l'action sit. Une application courante est le téléporteur. En effet on peut determiner la position d'assise mais elle n'est pas forcement sur l'objet lui même, la distance maximum est de 300m.
Le premier paramêtre est la distance relative par raport à notre objet. Attention ce n'est pas les coordonnées d'arrivé mais la distance entre les deux et il ne faut pas oublié de prendre en compte la rotation de l'objet sinon on se retrouve pas au même endroit.
Le deuxième paramètre est la rotation, ce n'est pas important dans le cadre d'un teleport la position finale alors on le mets à ZERO_ROTATION.
j'ai rajouté une autre fonction aujourd'hui llUnSit qui force l'avatar à se relever, sinon il arrive en position assise. Et on ne fait cette action que si il est assis dessus.

default
{
    state_entry()
    {
        // position de destination x,y,z
        vector Destination=<512,34,10>;

        // distance relative au teleport
        vector offset=(Destination-llGetPos())/llGetRot();

        // la fonction du jour
        llSitTarget(offset,ZERO_ROTATION);
    }
    // l'evenement se produit d'un changement avec un prim
    // dans le cas qui nous interesse je m'assieds ou je me lève
    changed(integer change)
    {
        // verifie si il s'agit d'un changement de liaison
        if(change==CHANGED_LINK)
        {
            // la fonction du jour
            key user=llAvatarOnSitTarget();

            // on verifie la presence de l'avatar
            if(user!=NULL_KEY)
                // remet debout l'avatar à la destination
                // sinon il arrive en position assise
                llUnSit(user);
        }
    }
}

jeudi 10 janvier 2008

llAvatarOnSitTarget


Nous allons commencer une nouvelle thématique avec la fonction llAvatarOnSitTarget(), comment gérer les liaisons et les animations entre prim avatar. Avec pour finalité, ce qu vous avez déjà vu partout dans second life les "pose ball".
Changed se produit quand une interaction vient de se produire avec l'objet. Dans notre cas, si un avatar s'assied ou se lève. Quand on s'assied sur un objet notre avatar est "linker", lié, à l'objet.
le integer change nous indique ce qu'il s'est passé, ici on test si c'est la liaison qui a été modifiée. Mais on ne sait pas s'il s'est levé ou assis. La fonction du jour va nous y aidée.
Elle permet de retourner la key de l'avatar assis sur l'objet, donc si la key n'est pas null c'est qu'il est assis et a contrario c'est qui vient de se lever

default
{
    // l'evenement se produit d'un changement avec un prim
    // dans le cas qui nous interesse je m'assieds ou je me lève
    changed(integer change)
    {
        // verifie si il s'agit d'un changement de liaison      
        if(change==CHANGED_LINK)
        {
            // la fonction du jour
            key user=llAvatarOnSitTarget();

            // on verifie la presence de l'avatar
            if(user!=NULL_KEY)
                llInstantMessage(user,"Suis je confortable?");
            else
                llInstantMessage(user,"merci de m'avoir utilise");
        }
    }
}

mercredi 9 janvier 2008

llListenRemove


Le llListenRemove est très simple à comprendre, il arrete l'ecoute que l'on avait lancé. la fonction llListen renvoit un integer, celui ci identifie de quelle ecoute on parle. Cet identifiant est pris en paramètre par llListenRemove pour etre arreté.
Mais pourquoi avoir fais ca me diriez vous? pour des raisons de sécurité de la vente et de lag.
Si on reprends note script d'hier, le dernier client peut profiter d'une faille car notre channel est toujours ouvert pour lui. Si il connait le channel(pas de bol quand même) il lui suffit de répeter sur ce channel les nom des objets et on lui donne tout ce que l'on veut.

Cette fois-ci c'est blindé car on ecoute que pour le client et une fois qu'il a eu son objet on ecoute plus.

Il y a l'effet lag qui est très important, en utilisant cette fonction, vous scriptez proprement...


// la liste des objet à vendre dans votre vendor
list obj=[];

// permetra l'identification du listen
integer IdListen;

default
{
    state_entry()
    {

        // donne le nombre d'objet contenu dans l'inventaire du prim
        integer NbObj=llGetInventoryNumber(INVENTORY_OBJECT);

        // compteur de boucle
        integer i;

        // rempli la list des objets
        // les acccolade ne sont pas nécéssaire car il n'y a que
        // une ligne dans la boucle
        for(i=0;i<NbObj;i++)
            obj+=llGetInventoryName(INVENTORY_OBJECT,i);
    }

    listen(integer channel, string name, key id, string message)
    {

        // donne l'objet acheté
        llGiveInventory(id,message);

        // la fonction du jour
        llListenRemove(IdListen);
    }
    money(key giver, integer amount)
    {
        // choisi un channel au hasard pour securisé
        integer mychannel=(integer)llFrand(1000.0)+5000;

        // ecoute le channel et concerve le id de l'ecoute
        IdListen=llListen(mychannel,"",giver,"");

        // laisse le choix de l'objet à l'utilisateur
        llDialog(giver,"Choisissez votre objet",obj,mychannel);
    }
}

mardi 8 janvier 2008

llGetInventoryName

Pour ceux qui aurait des difficultés avec ce script je fais cours demain sur "terra bordeaux" à l'ecole de SL et ce sujet sera abordé.

Le programme du jour est chargé car il y a deux fonctions. llGetInventoryNumber retourne le nombre de "content"(je trouve pas le mot en francais, à part truc) d'un type (notecard, object, script, etc..)
Et comme l'objectif de notre vendor est de vendre les object de l'inventaire, il nous faut savoir combien y en a.
Chaque objet ou "content" dans l'inventaire est numéroté, ainsi, avec la fonction llGetInventoryName, je peux lui demander de me dire le nom du niéme objet. Noter fonction prend deux paramètre le type de "content" et le numéro du "content".

Donc ces objets nous devons ajouter leur nom à notre list obj. Pour cela grace au for, la ligne est répété et la valeur de i change. Ainsi, on execute notre fonction pour chque objet et son resultat est ajouté à notre liste d'objet.

L'interet de ce système est de plus avoir à modifier son script des que l'on modifie son vendor pour de nouveaux objets. Désormais il marche pour tous...

// la liste des objet à vendre dans votre vendor
list obj=[];

// channel de communication pour la fenêtre lldialog
integer mychannel;

// key du client qui viens de payer
key client;
default
{
state_entry()
{

// choisi un channel au hasard pour securisé
mychannel=(integer)llFrand(1000.0)+5000;

// ecoute le channel
llListen(mychannel,"",NULL_KEY,"");

// donne le nombre d'objet contenu dans l'inventaire du prim
integer NbObj=llGetInventoryNumber(INVENTORY_OBJECT);

// compteur de boucle
integer i;

// le for permet de répeter des instructions plusieurs fois
// premier paramètre à combien on en commence i=0
// deuxieme parametre je le fais i // troisième paramètre à chaque tour j'augmente i de 1 i++
for(i=0;i {
// la fonction du jour
obj+=llGetInventoryName(INVENTORY_OBJECT,i);
}

}

listen(integer channel, string name, key id, string message)
{
// la fonction du jour
if(id==client)llGiveInventory(client,message);
}
money(key giver, integer amount)
{
// sauvegarde la key du client
client=giver;

// laisse le choix de l'objet à l'utilisateur
llDialog(client,"Choisissez votre objet",obj,mychannel);
}

}

lundi 7 janvier 2008

llGiveInventory

La fonction du jour permet de donner à un utilisateur un objet qui se trouve dans le contenu de celui-ci(inventaire de l'objet).
Imaginons que nous vendions deux tee-shirt, un modèle pour homme et un pour femme. Grâce à cette fonction on mets les deux tee shirt dans le vendor, un qui s'appelle homme et l'autre femme. Au moment de la vente on ne donnera que celui que veut le client.

Dans l'évènement money, comme ca on est sur que le client a payé, on affiche la fenêtre de dialog.
Et dans le listen, on verifie si c'est bien le client qui a fait le choix et cette fois-ci on donne l'objet grâce à la fonction.

La fonction attend deux paramètres la key du destinataire, et le nom de l'objet de l'inventaire


// la liste des objet à vendre dans votre vendor
list obj=["homme","femme"];

// channel de communication pour la fenêtre lldialog
integer mychannel;

// key du client qui viens de payer
key client;
default
{
state_entry()
{
// choisi un channel au hasard pour securisé
mychannel=(integer)llFrand(1000.0)+5000;

// ecoute le channel
llListen(mychannel,"",NULL_KEY,"");
}
listen(integer channel, string name, key id, string message)
{
// la fonction du jour
if(id==client)llGiveInventory(client,message);

}
money(key giver, integer amount)
{
// sauvegarde la key du client
client=giver;

// laisse le choix de l'objet à l'utilisateur
llDialog(client,"Choisissez votre objet",obj,mychannel);
}
}

vendredi 4 janvier 2008

llGiveMoney

La fonction d'aujourd'hui permet de faire ce que l'on appel un vendor partagé. C'est en effet très util quand on fait des ventes. Il permet de donnée une partie de son argent au propriétaire de la boutique. Ce qui est un contrat courant entre créateur est propriétaire de magasin.
Revenons à la fonction. llGiveMoney, elle prend deux paramètres une ke la personne à qui on envoit la somme et un integer qui est la somme à proprement parlé.
Vous aurez certainement remarqué, dans le state entry le llrequestPermission, nous nous etendrons pas sur le sujet pour l'instant car il s'agit d'une fonction difficile. Il faut juste retenir que un script ne peut donner votre argent sans votre accord et que cette fonction vous pose la question. Sans llRequestPermission pas de llGiveMoney.


// personne avec qui l'on veut partager sa vente
key destinataire="a822ff2b-ff02-461d-b45d-dcd10a2de0c2";

default
{
state_entry()
{
// demande au propiétaire si le script a le droit de donner de l'argent
// on va tout de même toucher à votre compte sans votre avis ^^
// cette fonction sera vu en detail ulterieurment
llRequestPermissions(llGetOwner(),PERMISSION_DEBIT);
}
// l'evenement money se produit quand un paiement à été fait à l'objet
// giver est la key de la personne ayant donné de l'argent et amount le montant
money(key giver, integer amount)
{
// ici on partage à 50% le montant recu
integer MontantPartage;
MontantPartage=(integer)amount/2;

// la fonction du jour
llGiveMoney(destinataire,MontantPartage);

// vite fait un petit message d'information pour le destinataire
llInstantMessage(destinataire, "vous aves recu " + (string)MontantPartage + " L$ de " + llKey2Name(llGetOwner()));
}
}

jeudi 3 janvier 2008

llInstantMessage

Cette fonction est très simple d'utilisation à partir de la Key d'un personne on paut lui envoyer un IM. Ici, on remerci le donneur par un IM, après tout, tout le monde n'a pas besoin de le savoir. En plus, ca flash bien comme message.
Donc deux paramètres le premier la key du destinataire, et le deuxième, le message


default
{
state_entry()
{
// affiche le texte en blanc au dessus de l'objet
llSetText("tip jar",<1.0,1.0,1.0>,1.0);

// defini le don
llSetPayPrice(PAY_DEFAULT, [50,100,200,PAY_HIDE]);
}

// l'evenement money se produit quand un paiement à été fait à l'objet
// giver est la key de la personne ayant donné de l'argent et amount le montant
money(key giver, integer amount)
{
// la fonction du jour
llInstantMessage(giver, llKey2Name(giver) + " merci pour le don");
}
}

mercredi 2 janvier 2008

llSetPayPrice

On va parler un peu d'argent, et oui, cela fait aussi parti de second life. Pour travailler on va utiliser un exemple simple la tip jar. llSetPayPrice permet d'afficher une petite fenêtre avec un menu de prix.
La fonction prend 2 paramètres le premier indique si l'on veut une fenêtre de saisie manuelle.
PAY_DEFAULT si on en veut une, sinon PAY_HIDE
Le second indique un tableau de 4 montant possible correspondant à différents choix.
si l'on veut moins de 4 choix on complète par PAY_HIDE

En utilisant llsetprice il n'est pas nécessaire de cocher la case à vendre... ca ne voudrais rien dire d'ailleurs

default
{
state_entry()
{
// affiche le texte en blanc au dessus de l'objet
llSetText("tip jar",<1.0,1.0,1.0>,1.0);

// la fonction du jour
llSetPayPrice(PAY_DEFAULT, [50,100,200,PAY_HIDE]);
}

// l'evenement money se produit quand un paiement à été fait à l'objet
// giver est la key de la personne ayant donné de l'argent et amount le montant
money(key giver, integer amount)
{
//llKey2Name tranforme l'UID d'une personne en son nom
llSay(PUBLIC_CHANNEL,llKey2Name(giver) + " merci pour avoir donne" + (string)amount + "L$" );
}
}