mercredi 9 avril 2008

llGetParcelPrimOwners


La fonction du jour permet de recupèrer une list de personne utilisant des prim sur une parcelle.
Notre exemple permet de dire combien d'objet possède la personne qui touche l'objet

La liste de retour à ce format [Key Av1, Integer PrimAv1,Key Av2, Integer PrimAv2,....]

default
{
    touch_start(integer total_number)
    {
        integer count=0;

        // identifie l'avatar qui touche
        key av=llDetectedKey(0);

        // la fonction du jour
        list OwnPrim=llGetParcelPrimOwners(llGetPos());

        // recherche dans la list l'avatar detecté
        integer i=llListFindList(OwnPrim,[av]);

        // recupère dans la liste les prims utiliser par l'avatar
        if(i!=0)count=llList2Integer(OwnPrim,i+1);

        // affiche un message du nombre de prim de l'avatar
        llSay(0, llKey2Name(av) + ", vous possedez sur cette parcelle " + (string)count + " prims");
    }
}

mardi 8 avril 2008

llGetParcelPrimCount


Désolé pour mon absence prolongée, mais LslToday est de retour.

La fonction du jour, llGetParcelPrimCount, permet de determiner le nombre de prim utilisés sur un terrain.
Elle prend trois paramètres:
- Un vecteur qui determine quelle parcelle de la sim doit être comptée.
- Une constante determinant qu'es ce que l'on doit compter
Category
Value
Meaning
PARCEL_COUNT_TOTAL 0 All prims on the parcel(s). Does not include temp on rez objects.
PARCEL_COUNT_OWNER 1 Prims owned by the parcel owner.
PARCEL_COUNT_GROUP 2 Prims not owned by the owner, but set to or owned by the group of the parcel.
PARCEL_COUNT_OTHER 3 Prims not set to group or owned by the owner.
PARCEL_COUNT_SELECTED 4 All prims selected or sat on.
PARCEL_COUNT_TEMP 5 All temp on rez objects.


- et un paramètre TRUE/FALSE  si on compte la sim en entier

default
{
    touch_start(integer total_number)
    {
        llSay(0, (string)llGetParcelPrimCount(llGetPos(), PARCEL_COUNT_TOTAL,FALSE));
    }
}

mercredi 6 février 2008

llEjectFromLand


La foction du jour, llEjectFromLand est assez explicite elle permet d'ejecter un avatar de son terrain.
En la combinant avec Sensor, nous avons fait notre petite alarme maison.
La fonction ne prends que un seul paramètre une Key qui est la personne qui doit etre éjecté.

default
{
    state_entry()
    {
        //verifie la présence d'avatar dans un rayon de 50m toute les 30 sec
        llSensorRepeat("",NULL_KEY,AGENT,50,TWO_PI,30);
    }


    sensor(integer total_number)
    {
        //l'evenement sensor fonctionne comme touch et fournie le nombre de personnes detectées
        integer i;
        //on boucle sur toutes les personnes detectés
        for(i=0;i<total_number;i++)
        {
            // si la personne detecté n'est pas le propriétaire on lui donne un avertissement
            if(llDetectedKey(0)!=llGetOwner())
            {
                // la fonction du jour
                llEjectFromLand(llDetectedKey(0));
            }
        }
    }
}

mardi 5 février 2008

llSensorRepeat


La fonction llSensorRepeat est strictement identique à la fonction sensor que nous avons vu hier, ca particularité:
Elle possède un paramètre supplémentaire qui est la régularité d'excution qui est fixé en seconde.
Ainsi vous pouvez detecter de manière répétitive une cible. Comme une porte de supermarché qui attends que quelqu'un s'approche pour s'ouvrir



default
{
    state_entry()
    {
         //la fonction du jour
        llSensorRepeat("",NULL_KEY,AGENT,50,TWO_PI,30);
    }


    sensor(integer total_number)
    {
        //l'evenement sensor fonctionne comme touch et fournie le nombre de personnes detectées
        int i;
        //on boucle sur toutes les personnes detectés
        for(i=0;i<total_number;i++)
        {
            // si la personne detecté n'est pas le propriétaire on lui donne un avertissement
            if(llDetectedKey(0)!=llGetOwner())
                llSay(PUBLIC_CHANNEL,"vous n'etes pas le proprietaire, partez");
        }
    }
}

lundi 4 février 2008

llSensor


La fonction llSensor est très puissante. Elle permet de detecter differentes choses dans une zone. Il faut parcontre l'utiliser avec mesure car elle génère du lag. Elle est très utilisé pour les alarmes qui est un peu le principe de notre script.
La fonction prends 5 paramètres:
Un string qui est le nom de la personne ou objet rechercher
Une key de la personne ou objet rechercher
Un integer qui est le type de chose recherché, object agent...
Un integer qui est la portée qui ne peut excéder 96m (ce qui est gigantesque, utiliser des distances trees courtes)
Et pour fini l'arc, il s'agit de l'angle exprimé en radiant dans notre cas il recherche dans une sphère

default
{
    touch_start(integer total_number)
    {
        //la fonction d jour
       llSensor("",NULL_KEY,AGENT,50,TWO_PI);
    }
    sensor(integer total_number)
    {
        //l'evenement sensor fonctionne comme touch et fournie le nombre de personnes detectées        
        int i;
        //on boucle sur toutes les personnes detectés        
        for(i=0;i<total_number;i++)        
        {
            // si la personne detecté n'est pas le propriétaire on lui donne un avertissement
            if(llDetectedKey(0)!=llGetOwner())
                llSay(PUBLIC_CHANNEL,"vous n'etes pas le proprietaire, partez");
        }
    }
}

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);
    }
}