Tutoriel [Skript] ENORME Tuto! Créez des plugins sans Java!

AstroTiger_

Bucheron
27 Mai 2017
48
0
11
22
Salut à tous!
Je vous propose aujourd'hui un grand tuto sur le plugin Skript qui permet à son tour de faire des plugins pour Minecraft! N'hésitez pas à me dire ce qui ne vas pas ou ce qui est mal expliqué pour que je règle ça ;)
Pour trouver la version de Skript qui marche avec votre version Minecraft je vous redirige vers un de mes sujets sur le forum Skript-MC: https://skript-mc.fr/forum/threads/packs-skript-addons-liens-de-téléchargement-officiels-de-chaque-addon-1-7-1-8-1-9-1-10-1-11.7684/
Je vous invite à rejoindre la communauté francophone de Skript-mc qui se fera un plaisir de vous aider: https://skript-mc.fr/forum/
Pour finir, vous pouvez avoir plein d'addons et documentation sur ce site: https://www.skunity.com/

Qu'est ce que c'est??

Skript est un plugin qui permet de créer d'autres plugins pour votre serveur Minecraft mais en bien plus simple. Le langage est ici extrêmement simple. Les seules compétences à avoir pour pouvoir coder en Skript est de savoir parler un minimum anglais!
Mais pourquoi choisir Skript plutôt que le java par exemple?
Je vous ai fait ci-dessous un comparatif de l'un par rapport à l'autre:

Les avantages du Skript:
- Langage simple
- Création du plugin rapide (pas besoin de compilation)
- Pas besoin de reload TOUS le serveur pour reload un plugin
- Besoin seulement d'un éditeur de texte pour coder (pas d'IDE)

Les inconvénients:
- Implémentation d'API externe impossible sans addon (exemple d'APIs: Citizens, WorldGuard, TagAPI etc...)
- Limite du code (exemple: Création de Threads, d'Object...)
- Langage non universel (la publication d'un plugin en Skript est plus difficile qu'un plugin en java qui peut être mis facilement sur un serveur)
- Un peu plus lent que le Java

Je vous ai fait une comparaison des deux languages

Pour annuler la casse d'un bloc si le joueur ne tient pas une pioche en diamant (exemple totalement pourri)
En Skript:

Code:
on break: #Quand le bloc est cassé
    if player's tool is not diamond pickaxe: #Si le joueur ne tient pas une pioche en diamant
        cancel event # Annuler l'evenement


En Java:

Code:
@EventHandler //Annontation
public void onBreak(BlockBreakEvent e) { //Quand un bloc est cassé
    if(e.getPlayer().getItemInHand().getType()!=Material.DIAMOND_PICKAXE) { //Si le joueur de tient pas une pioche en diamant
        e.setCancelled(true); //Annuler l'evenement
    }
}

Pour envoyer "Hey <joueur>, tu nous avait manqué!" quand un joueur se connecte
En Skript:

Code:
on join: #Quand le joueur rejoint le serveur
    send "Hey %player%, tu nous avait manqué!" to player #Envoyer ce message au joueur ayant rejoint

En Java:

Code:
@EventHandler //Annotation
public void onJoin(PlayerJoinEvent e) { //Quand le joueur se connecte
    e.getPlayer().sendMessage("Hey " + e.getPlayer().getName() + ", tu nous avait manqué!"); //Envoyer le message
}


Dernier exemple, quand un zombie meurt, ça fait spawner 3 bébés zombies où il est mort que si il est dans le monde "game"(pour le Skript, je devrais utiliser un add-on car le plugin de base ne contient pas la fonction dont j'ai besoin)
En Skript:

Code:
on death of zombie: #A la mort d'un zombie
    if victim's age is adult: #Si il est adulte (car si il est bébé ça le fera quand même et ça on le veut pas)
        if victim's world is "game": #Si le monde est "game"
            spawn 3 baby zombie at victim #Fait spawn 3 bébés zombies où l'adulte est mort

En Java:

Code:
@EventHandler //Annotation
public void onDeathOfZombie(EntityDeathEvent e) { //Quand un zombie meurt
    if(e.getEntity() instanceof Zombie) { //Si l'entité est un zombie
        if(!e.getEntity().isBaby) { //Si il n'est pas un bébé
            World world = e.getEntity().getLocation().getWorld(); //Je récupère le monde où je dois faire spawner les zombies
            Location loc = e.getEntity().getLocation(); //Je récupère l'endroit où je devrais faire spawner les zombies
            if(world.getName()=="game") { //Je vérifie si le monde s'appelle "game"
                EntityZombie ez1 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez1.setBaby(true); //Je le change en bébé
                EntityZombie ez2 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez2.setBaby(true); //Je le change en bébé
                EntityZombie ez3 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez3.setBaby(true); //Je le change en bébé
            }
        }
    }
}

Comme vous le voyez, le skript est bien plus simple mais il a des limites comme les fonctions qu'il n'y a pas dans le plugin Skript de base. C'est pourquoi j'ai du utiliser un autre plugin qui vient en complément de Skript.
Vous pourrez obtenir tous les autres plugins ici: http://www.skunity.com/


Comment ça marche le Skript?

Je vais tous d'abord vous apprendre à créer le fichier qui contiendra votre code. Vous devez tous d'abord aller à la racine de votre serveur puis dans plugins/Skript/scripts/. Si vous n'avez encore jamais touché à ce dossier, vous devriez avoir plein de fichier. Ce sont des codes que le développeur a mis. Vous remarquerez qu'ils ont tous un nom du style "- %nom%.sk", c'est normal, si un fichier de code pour Skript à un "-" devant son nom, c'est que ce fichier est désactivé. Vous pouvez supprimer tous ces fichiers si vous en avez pas besoin.
Ensuite vous allez créer votre propre fichier. Vous ouvrez votre éditeur de texte préféré (J'utilise Notepad++ qui est très bien: http://notepad-plus-plus.org/fr). Ensuite vous enregistrez sous votre fichier vierge dans le dossier plugins/Skript/scripts sous le nom suivant:
"%nom que je veux%.sk". Le .sk est très important, si vous mettez .txt le plugin ne lira tous simplement pas ce fichier.
Voila, vous avez votre premier fichier de code. Mais bien sur vous n'avez rien mis donc ça ne fera rien.
Pour reload (donc redémarrer votre plugin) vous faites en jeu soit "/skript reload all" pour reload tous les plugins Skript soit "/skript reload %nom de votre fichier sans le .sk%" pour redémarrer que un seul plugin.
Et en Skript, si une ligne finie par ":", la ligne suivante contiendra un TAB (Le tab est ici sur votre clavier: http://lilapuce.net/IMG/jpg/clavier_pour_tab.jpg) de plus que la précédente.
Voici un exemple

Code:
on death: #Je met un espace en plus! (donc 1 TAB)
    if victim's world is "world": #Je met un TAB en plus (donc ca fait 2 TAB en tout)
        broadcast "COUCOU" #Ca ne finit pas par : donc pas de TAB en plus
        damage attacker by 255 hearts #Toujours pas de TAB en plus

La dernière chose à savoir avant de passer au chapitre suivant est que le Skript est composé comme le Java (pour Minecraft) en 3 étapes:
- L'évenement 1 seule fois au début (la seule exception est pour créer un commande)
- Les conditions eventuellement mais quasi indispensable
- Les actions (ou effects) qui sont ce qui sera fait

Les événements

Tous d'abord nous allons commencer par les événements. Mais c'est quoi un événement? :confused:
Un événement est une actions produite sur le serveur soit par un joueur, une entité, le serveur lui même etc...
Voici des exemples d’événements:
on join: #Quand le joueur rejoint le serveur
on death: #Quand une entité meurt
on pressure plate: #Quand une entité marche sur une plaque de pression
on break: #Quand un joueur casse un bloc
on place: #Quand un joueur pose un bloc
on craft: # Quand un joueur craft un item
...
Si vous voulez la liste des événements, ils sont disponibles ici: http://njol.ch/projects/skript/doc/events/
Il faut ensuite savoir qu'un événement fini toujours par ":". Un événement ne peut pas être lui même dans un événement. C'est pourquoi il n'y aura JAMAIS de tab devant un événement.

Les conditions

Une condition permet de vérifier si telle ou telle chose vaut ceci, est vrai etc...
Voici des exemple concrets:
- Si le joueur s'appelle "Jean-Kevin"
- Si le monde s'appelle "paradis"
- Si l’expérience du joueur est plus grande que 14
- Si l'entité est empoisonnée
etc...
Une condition pourra être suivie d'un "else:" ou "else if ...:" traduits par "sinon" et "sinon si..."
Ça permet que si la conditions n'est pas vérifiée (exemple: Si le joueur est op, si ce n'est pas vérifié (donc qu'il n'est pas op)) ça fera ce qui est dans le "else"
Ensuite, une condition commencera toujours par if (sauf exception) et se finira par ":"
Pour tester une conditions vous devez ensuite mettre un comparateur (égal, plus grand etc...)
Voici une liste:
is (est égal)
is greater than (est plus grand que)
is smaller than (est plus petit que)
is not (n'est pas égal)
is between %valeur% and %valeur% (est entre ces deux valeurs)
has (possède)

Ces comparatifs se situent ici:
if player's health is 5: (si la vie du joueur est 5)
Elle se situe donc entre le "if %valeur%" et ce qui est testé donc ici 5

Autres exemples:
if "%damage cause%" is "void": #Si la cause des dégâts est le vide
if player's tool is diamond pickaxe: #Si le joueur tient une pioche en diamant
if player's food level is greather than 3: #Si la faim du joueur est plus grande que 3
if altitude of attacker is smaller than altitude of victim: #Si l'altitude de l'attaquant est inférieure a celle de la victime
if y-location of player is between 50 and 64: #Si la location y du joueur est entre 50 et 64
if player has permission "skript.exemple": #Si le joueur a la permission "skript.exemple"

Pour la liste des conditions c'est ici: http://njol.ch/projects/skript/doc/conditions/
et ici: http://njol.ch/projects/skript/doc/expressions/

Les exceptions:
Je vous avais parlé d'exceptions au-dessus. Nous y voilà!
Ces exceptions sont des conditions qui ne contiennent pas de if au debut. Elle ne terminent pas non plus par ":". Ces conditions peuvent être utilisées si vous voulez un code moins long et si vous n'avez pas de else ensuite.
Exemples:
player's health is 10 (équivaut à if player's health is 10: )
experience of player is greater than 16 (équivaut à if experience of player is greater than 16: )
player is flying (équivaut à if player is flying: )

Les actions

Les actions sont ce qui va être fait lorsque l’événement à été produit et après les éventuelles conditions (voir entre 2 conditions).
Elles vont souvent utiliser les acteurs de l'action comme le joueur l'ayant fait, le type de bloc cassé etc...
La liste des actions est ici: http://njol.ch/projects/skript/doc/effects
Exemples d'actions:
push the player upward at speed 10 #Éjecter le joueur a une vitesse de 10 vers le haut
cancel event #Annuler l'événement
teleport victim to attacker #téléporter la victime a l'attaquant

Un petit point sur l'action "cancel event":
Cette action permet d'annuler TOUS ce que l’événement vas faire
Exemple:
Code:
on break:
    cancel event

Ici quand un bloc va être cassé, tous va être annulé!
Donc ça nous fait:
- Le bloc va être reposé
- Les dégâts subit par l'outils du joueur va être annulé
- Les drops effacé
etc...


Un exemple de Skript pour ces 3 étapes:

Code:
on join: #Evennement
    if player has permission "skript.exemple": #Condition
        if player's world is "survie": #Condition
            send "&aBon jeu dans le monde survie!" to player #Action
        else if player's world is "gateau": #Condition
            send "&aBon app dans le monde gateau!" to player #Action
        else: #Condition non verifiée
            kill the player #Action
            player is op #Condition!!!!
            send "&cPardon monsieur l'admin!" to player #Action

Les boucles (ou loops):

Je vais parler ici des boucles. Ces boucles permettent de tester toutes les valeurs pour la boucle souhaitée.
Exemple:
loop all players: #tester tous les joueurs
loop all entities in world "hell": #tester toutes les entités dans le monde "hell"
loop all items in inventory of player: #tester tous les items dans l'inventaire du joueur

Les boucles finissent elles aussi par ":" et donc la ligne suivante aura 1 TAB en plus
Lorsque vous avez déclaré une boucle, une nouvelle "expression" va être créée nommé souvent "loop-%type de loop%" a part pour les variables mais on en parlera plus tard.
Exemples:
Code:
loop all players:
    if loop-player is in world "jean-pierre":
        send "THUG LIFE!" to loop-player #Je suis désolé j'ai plus d'idées rationnelles :/
loop all items in player inventory:
    if loop-item is diamond pickaxe:
        set loop-item to air
        send "Adieu la pioche en diamant de %player% MOUAHAHA &kkkkkkkkk" to player


Les commandes:

Vous déclarez une commande à la place d'un événement comme ceci:
Code:
command /nomdelacommande:
    trigger:

Le trigger est a partir de l'endroit où les conditions et actions commenceront. Avant vous pouvez mettre les descriptions, qui peut les exécuter etc... Sachez que ceci n'est pas obligé d'être mis, perso je ne les met pas ^^
Voici ce que vous pouvez mettre avant le trigger:
- description: La description de ce que fait la commande
- usage: Comment la commande doit être utilisée, ex: /nomdelacommande <arguments>
- permission: les.permissions.necessaires
- permission message: Le message affiché si le joueur n'a pas la permission
- executable by: Qui peut exécuter la commande: players, console OU players and console
- aliases: Les abréviations pour exécuter la commande, ex: /c

Pour les arguments vous devez ajouter <type d'argument> après le "command /nomdelacommande:"
Exemple:
Code:
command /abcdef <text> <int>:
    trigger:

Dans les conditions et actions vous allez devoir utiliser "arg 1/2/3..." ou "%argument 1%" si vous voulez l'inclure dans une variable comme dans un message par exemple
Exemple:
Code:
command /coucou <player>:
    trigger:
        send "&bCOUCOU %argument 1%" to arg 1

Les variables:

Il existe en Skript 3 types de variables:
- Les variables temporaires
- Les variables enregistrées
- Les groupes de variables

Les variables sont définies et utilisées entre des {}. Elles peuvent également contenir des ".".
Exemple:
{coucou}
{variable}
{skript.test}

Les variables contiennent une valeur (a part pour les groupes) et peuvent être changées ou implémentées dans un texte ou une condition
Une variable temporaire contient un _ avant le nom. Cette variable ne sera pas sauvegardée et si 2 même événements sont produits en même temps, même si les variables utilisées ont le même nom, elles pourront être différentes. Ces variables seront également supprimées à la fin de l'événement.
Exemple:
{_coucou}
{_variable}
{_skript.test}

Les variables enregistrées ou fixes sont sauvegarder dans une base de données et peuvent être réutilisées ou changées à n'importe quel moment.
Exemple:
{coucou}
{variable}
{skript.test}

Pour finir nous avons les groupes de variables, ce sont des groupes contenants plein de variables. Avec une boucle, nous pouvons tester toutes les variables contenues dans ce groupe. Ils sont définis avec "::" après le nom
De plus, si vous mettez "::*", c'est le groupe en entier qui est sélectionnée et si vous mettez "::%nom d'une variable%", ce sera juste la variable avec ce nom dans ce groupe qui sera sélectionnée.
Ce groupes peuvent contenir n'importe quelle données aussi, comme des noms de joueur, des UniqueUID, des entités, des localisations...
Exemple:
{list.skript::*}
{joueur.op::*}

Si vous utilisez une variable dans du code, elle sera remplacée par la valeur la contenant:
Exemple:
if {time.player} is greater than 45:

Ici {time.player} sera remplacée par la valeur la contenant.
Autre exemple:
teleport player to {location.spawn}

Si la variable {location.spawn} est bien une localisation, ça marchera. Si la variable est imaginons 5, rien ne se passera car une joueur ne peut pas être téléporter a un nombre
Les variables peuvent également être utilisées dans les textes et elles seront remplacées par leur valeur mais elles devront être contenues entre des %.
Exemple:
broadcast "%player% a joué %{time.%player%}%"

Pour éditer une variable, vous utiliserez ceci:
- set {var} to location of player #La variable sera la position du joueur
- add 5 to {var} #On ajoutera 5 à la variable
- remove 9 from {var} #9 sera retiré de la variable
- clear {var} #La variable sera effacée


Les événements on death et on damage:

Dans ces deux événements, il n'y aura pas de player mais un "attacker" et une "victim"
attacker est celui qui tue ou qui fait les dégâts et victim est celui qui meurt ou reçoit les dégâts


Dernier point sur les textes et les variables:

Pour utiliser un nom ou valeur contenu dans les acteurs de l'event (nom de joueur, type de bloc cassé...) dans un texte ou le nom d'une variable, vous devrez mettre des % autour de la valeur voulu:
Exemples:
broadcast "%player% est gentil"
broadcast "%player% a cassé un(e) %event-block%"
add 1 to {time.%player%}
Les boucles pour les variables:

Je vais vour apprendre ici à faire une boucle pour un groupe de variable (donc qui fini par ::*). Voici la démarche à entreprendre:
Vous devez mettre "loop {ma.variable::*}:". Attention! Il faut bien que ce soit ::* à la fin et non ::variable ou autre.
Ensuite vous obtiendrais 2 valeurs pour la boucle nommées "loop-index" et "loop-value".
Loop-index est l'index de la boucle. Par exemple, si votre boucle en ai à la 20ème variables du groupe, loop-index vaudra 20.
Loop-value est la valeur contenu dans la variable testée. Si vous en êtes à la 20ème variable, vous allez obtenir la valeur de la 20ème variable.

Exemples de Skript:

Ce Skript permet de faire un casino. Pour qu'il marche il faut faire d'abord "/casino give" et cliqué successivement sur les 3 blocs qui changeront puis de mettre un bouton avec au-dessus un panneau avec
"&a[CASINO]" (un plugin de couleur sur les panneaux est necessaire)
""
"Cliquez pour"
"jouer"

Et en dessous un panneau avec:
"&a[CASINO]"
""
"Pret"
""

Code:
command /casino <text>: #Commande pour give les items pour indiquer les blocs
    trigger:
        if player is op:
            if arg 1 is "give":
                give 1 glowstone dust named "&aBloc 1 casino" to player
                give 1 glowstone dust named "&aBloc 2 casino" to player
                give 1 glowstone dust named "&aBloc 3 casino" to player

on rightclick on button: #Quand on clic sur le bouton
    if block above event-block is sign: #Début de la verification des panneaux
        line 1 of block above event-block is "&a[CASINO]"
        line 3 of block above event-block is "Cliquez pour"
        line 4 of block above event-block is "jouer"
        if block 1 under event-block is sign:
            line 1 of block under event-block is "&a[CASINO]"
            if line 3 of block under event-block is "&kaaaaaaa":
                send "&cUne partie est déjà en cours!&r" to player
                stop
            else: #Fin de la vérification des panneaux
                if {points.%uuid of player%} is greater than 99: #Si le joueur a assez de points
                    set line 3 of block under event-block to "&kaaaaaaa" #Mettre en ligne 3 du panneaux en dessous: "&kaaaaaaa"
                    remove 100 from {points.%uuid of player%} #Enlever 100 points au joueurs
                    set {_loop} to a random number between 10 and 30 #Début de la boucle qui change les blocs
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block1} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block1} to red wool
                            else:
                                set block at {casino.block1} to green wool
                        chance of 33%:
                            set block at {casino.block2} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block2} to red wool
                            else:
                                set block at {casino.block2} to green wool
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block1} is red wool:
                        set {_1} to 1
                    if block at {casino.block1} is blue wool:
                        set {_1} to 2
                    if block at {casino.block1} is green wool:
                        set {_1} to 3
                    set {_loop} to a random number between 10 and 30
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block2} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block2} to red wool
                            else:
                                set block at {casino.block2} to green wool
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block2} is red wool:
                        set {_2} to 1
                    if block at {casino.block2} is blue wool:
                        set {_2} to 2
                    if block at {casino.block2} is green wool:
                        set {_2} to 3
                    set {_loop} to a random number between 10 and 30
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block3} is red wool:
                        set {_3} to 1
                    if block at {casino.block3} is blue wool:
                        set {_3} to 2
                    if block at {casino.block3} is green wool:
                        set {_3} to 3 #Fin des boucles qui change les blocs
                    if {_1} is {_2}: #Verification si les blocs 1 et 2 sont identiques
                        if {_2} is {_3}: #Verification si les blocs 2 et 3 sont identiques (par conséquent les blocs 1 et 3 sont identiques)
                            send "&aVous avez gagné 750 points!" to player
                            add 750 to {points.%uuid of player%} #Ajout des points
                        else:
                            send "&cDommage vous avez perdu..." to player
                    else:
                        send "&cDommage vous avez perdu..." to player
                    set line 3 of block under event-block to "&aPrêt"
                else:
                    send "&cVous n'avez pas assez de points pour jouer!&r"

on rightclick holding glowstone dust: #Event qui permet de definir les blocs
    if name of player's tool is "&aBloc 1 casino":
        set {casino.block1} to location of clicked block
        clear player's tool
    if name of player's tool is "&aBloc 2 casino":
        set {casino.block2} to location of clicked block
        clear player's tool
    if name of player's tool is "&aBloc 3 casino":
        set {casino.block3} to location of clicked block
        clear player's tool

Exercices et TP

Exercice 1: Essayez de savoir à quoi sert ce Skript (Facile!)

Code:
on craft:
    if event-item is diamond pickaxe or diamond shovel or diamond sword or diamond hoe or diamond axe:
        chance of 33%:
            give 1 diamond to player
            send "&aVous avez un diamant dont vous n'avez pas eu besoin pour votre craft!" to player

Réponse:
Il y a 1/3 pour que lors du craft d'un outils en diamant, le joueur récupère 1 diamant

Code:
on craft: #Evévenement: lors du craft
    if event-item is diamond pickaxe or diamond shovel or diamond sword or diamond hoe or diamond axe: #Si l'item crafté est en diamant
        chance of 33%: #33% de chance (donc 1/3)
            give 1 diamond to player #Donner 1 diamant au joueur
            send "&aVous avez un diamant dont vous n'avez pas eu besoin pour votre craft!" to player #Envoyer le message au joueur

Exercice 2: Créez ce Skript: (Facile!)
Lors d'un clic droit sur de l'herbe, si la faim du joueur n'est pas au max ça lui redonne 1 barre de faim et le bloc cliqué devient de la terre

Réponse:
Code:
on rightclick on grass: #Evénement clic droit sur de l'herbe
    if player's food level is not 10: #Si la faim du joueur n'est pas à 10 (donc le maximum)
        set player's food level to player's food level + 1 #Ajouter 1 barre de faim
        set clicked block to dirt #Le bloc cliqué devient de la terre
Bonjour, j'aimerais savoir comment faire en sorte qu'un inventaire s'ouvre quand je click sur un item au sol, pour moi c'est un atm. Car quand j'éssaye l'inventaire s'ouvre mais quand j'ai un item dans la mains et non quand le block est posé
 

AstroTiger_

Bucheron
27 Mai 2017
48
0
11
22
Salut à tous!
Je vous propose aujourd'hui un grand tuto sur le plugin Skript qui permet à son tour de faire des plugins pour Minecraft! N'hésitez pas à me dire ce qui ne vas pas ou ce qui est mal expliqué pour que je règle ça ;)
Pour trouver la version de Skript qui marche avec votre version Minecraft je vous redirige vers un de mes sujets sur le forum Skript-MC: https://skript-mc.fr/forum/threads/packs-skript-addons-liens-de-téléchargement-officiels-de-chaque-addon-1-7-1-8-1-9-1-10-1-11.7684/
Je vous invite à rejoindre la communauté francophone de Skript-mc qui se fera un plaisir de vous aider: https://skript-mc.fr/forum/
Pour finir, vous pouvez avoir plein d'addons et documentation sur ce site: https://www.skunity.com/

Qu'est ce que c'est??

Skript est un plugin qui permet de créer d'autres plugins pour votre serveur Minecraft mais en bien plus simple. Le langage est ici extrêmement simple. Les seules compétences à avoir pour pouvoir coder en Skript est de savoir parler un minimum anglais!
Mais pourquoi choisir Skript plutôt que le java par exemple?
Je vous ai fait ci-dessous un comparatif de l'un par rapport à l'autre:

Les avantages du Skript:
- Langage simple
- Création du plugin rapide (pas besoin de compilation)
- Pas besoin de reload TOUS le serveur pour reload un plugin
- Besoin seulement d'un éditeur de texte pour coder (pas d'IDE)

Les inconvénients:
- Implémentation d'API externe impossible sans addon (exemple d'APIs: Citizens, WorldGuard, TagAPI etc...)
- Limite du code (exemple: Création de Threads, d'Object...)
- Langage non universel (la publication d'un plugin en Skript est plus difficile qu'un plugin en java qui peut être mis facilement sur un serveur)
- Un peu plus lent que le Java

Je vous ai fait une comparaison des deux languages

Pour annuler la casse d'un bloc si le joueur ne tient pas une pioche en diamant (exemple totalement pourri)
En Skript:

Code:
on break: #Quand le bloc est cassé
    if player's tool is not diamond pickaxe: #Si le joueur ne tient pas une pioche en diamant
        cancel event # Annuler l'evenement


En Java:

Code:
@EventHandler //Annontation
public void onBreak(BlockBreakEvent e) { //Quand un bloc est cassé
    if(e.getPlayer().getItemInHand().getType()!=Material.DIAMOND_PICKAXE) { //Si le joueur de tient pas une pioche en diamant
        e.setCancelled(true); //Annuler l'evenement
    }
}

Pour envoyer "Hey <joueur>, tu nous avait manqué!" quand un joueur se connecte
En Skript:

Code:
on join: #Quand le joueur rejoint le serveur
    send "Hey %player%, tu nous avait manqué!" to player #Envoyer ce message au joueur ayant rejoint

En Java:

Code:
@EventHandler //Annotation
public void onJoin(PlayerJoinEvent e) { //Quand le joueur se connecte
    e.getPlayer().sendMessage("Hey " + e.getPlayer().getName() + ", tu nous avait manqué!"); //Envoyer le message
}


Dernier exemple, quand un zombie meurt, ça fait spawner 3 bébés zombies où il est mort que si il est dans le monde "game"(pour le Skript, je devrais utiliser un add-on car le plugin de base ne contient pas la fonction dont j'ai besoin)
En Skript:

Code:
on death of zombie: #A la mort d'un zombie
    if victim's age is adult: #Si il est adulte (car si il est bébé ça le fera quand même et ça on le veut pas)
        if victim's world is "game": #Si le monde est "game"
            spawn 3 baby zombie at victim #Fait spawn 3 bébés zombies où l'adulte est mort

En Java:

Code:
@EventHandler //Annotation
public void onDeathOfZombie(EntityDeathEvent e) { //Quand un zombie meurt
    if(e.getEntity() instanceof Zombie) { //Si l'entité est un zombie
        if(!e.getEntity().isBaby) { //Si il n'est pas un bébé
            World world = e.getEntity().getLocation().getWorld(); //Je récupère le monde où je dois faire spawner les zombies
            Location loc = e.getEntity().getLocation(); //Je récupère l'endroit où je devrais faire spawner les zombies
            if(world.getName()=="game") { //Je vérifie si le monde s'appelle "game"
                EntityZombie ez1 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez1.setBaby(true); //Je le change en bébé
                EntityZombie ez2 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez2.setBaby(true); //Je le change en bébé
                EntityZombie ez3 = (EntityZombie) world.spawnCreature(loc, EntityType.ZOMBIE); //Je fais spawn un zombie normal
                ez3.setBaby(true); //Je le change en bébé
            }
        }
    }
}

Comme vous le voyez, le skript est bien plus simple mais il a des limites comme les fonctions qu'il n'y a pas dans le plugin Skript de base. C'est pourquoi j'ai du utiliser un autre plugin qui vient en complément de Skript.
Vous pourrez obtenir tous les autres plugins ici: http://www.skunity.com/


Comment ça marche le Skript?

Je vais tous d'abord vous apprendre à créer le fichier qui contiendra votre code. Vous devez tous d'abord aller à la racine de votre serveur puis dans plugins/Skript/scripts/. Si vous n'avez encore jamais touché à ce dossier, vous devriez avoir plein de fichier. Ce sont des codes que le développeur a mis. Vous remarquerez qu'ils ont tous un nom du style "- %nom%.sk", c'est normal, si un fichier de code pour Skript à un "-" devant son nom, c'est que ce fichier est désactivé. Vous pouvez supprimer tous ces fichiers si vous en avez pas besoin.
Ensuite vous allez créer votre propre fichier. Vous ouvrez votre éditeur de texte préféré (J'utilise Notepad++ qui est très bien: http://notepad-plus-plus.org/fr). Ensuite vous enregistrez sous votre fichier vierge dans le dossier plugins/Skript/scripts sous le nom suivant:
"%nom que je veux%.sk". Le .sk est très important, si vous mettez .txt le plugin ne lira tous simplement pas ce fichier.
Voila, vous avez votre premier fichier de code. Mais bien sur vous n'avez rien mis donc ça ne fera rien.
Pour reload (donc redémarrer votre plugin) vous faites en jeu soit "/skript reload all" pour reload tous les plugins Skript soit "/skript reload %nom de votre fichier sans le .sk%" pour redémarrer que un seul plugin.
Et en Skript, si une ligne finie par ":", la ligne suivante contiendra un TAB (Le tab est ici sur votre clavier: http://lilapuce.net/IMG/jpg/clavier_pour_tab.jpg) de plus que la précédente.
Voici un exemple

Code:
on death: #Je met un espace en plus! (donc 1 TAB)
    if victim's world is "world": #Je met un TAB en plus (donc ca fait 2 TAB en tout)
        broadcast "COUCOU" #Ca ne finit pas par : donc pas de TAB en plus
        damage attacker by 255 hearts #Toujours pas de TAB en plus

La dernière chose à savoir avant de passer au chapitre suivant est que le Skript est composé comme le Java (pour Minecraft) en 3 étapes:
- L'évenement 1 seule fois au début (la seule exception est pour créer un commande)
- Les conditions eventuellement mais quasi indispensable
- Les actions (ou effects) qui sont ce qui sera fait

Les événements

Tous d'abord nous allons commencer par les événements. Mais c'est quoi un événement? :confused:
Un événement est une actions produite sur le serveur soit par un joueur, une entité, le serveur lui même etc...
Voici des exemples d’événements:
on join: #Quand le joueur rejoint le serveur
on death: #Quand une entité meurt
on pressure plate: #Quand une entité marche sur une plaque de pression
on break: #Quand un joueur casse un bloc
on place: #Quand un joueur pose un bloc
on craft: # Quand un joueur craft un item
...
Si vous voulez la liste des événements, ils sont disponibles ici: http://njol.ch/projects/skript/doc/events/
Il faut ensuite savoir qu'un événement fini toujours par ":". Un événement ne peut pas être lui même dans un événement. C'est pourquoi il n'y aura JAMAIS de tab devant un événement.

Les conditions

Une condition permet de vérifier si telle ou telle chose vaut ceci, est vrai etc...
Voici des exemple concrets:
- Si le joueur s'appelle "Jean-Kevin"
- Si le monde s'appelle "paradis"
- Si l’expérience du joueur est plus grande que 14
- Si l'entité est empoisonnée
etc...
Une condition pourra être suivie d'un "else:" ou "else if ...:" traduits par "sinon" et "sinon si..."
Ça permet que si la conditions n'est pas vérifiée (exemple: Si le joueur est op, si ce n'est pas vérifié (donc qu'il n'est pas op)) ça fera ce qui est dans le "else"
Ensuite, une condition commencera toujours par if (sauf exception) et se finira par ":"
Pour tester une conditions vous devez ensuite mettre un comparateur (égal, plus grand etc...)
Voici une liste:
is (est égal)
is greater than (est plus grand que)
is smaller than (est plus petit que)
is not (n'est pas égal)
is between %valeur% and %valeur% (est entre ces deux valeurs)
has (possède)

Ces comparatifs se situent ici:
if player's health is 5: (si la vie du joueur est 5)
Elle se situe donc entre le "if %valeur%" et ce qui est testé donc ici 5

Autres exemples:
if "%damage cause%" is "void": #Si la cause des dégâts est le vide
if player's tool is diamond pickaxe: #Si le joueur tient une pioche en diamant
if player's food level is greather than 3: #Si la faim du joueur est plus grande que 3
if altitude of attacker is smaller than altitude of victim: #Si l'altitude de l'attaquant est inférieure a celle de la victime
if y-location of player is between 50 and 64: #Si la location y du joueur est entre 50 et 64
if player has permission "skript.exemple": #Si le joueur a la permission "skript.exemple"

Pour la liste des conditions c'est ici: http://njol.ch/projects/skript/doc/conditions/
et ici: http://njol.ch/projects/skript/doc/expressions/

Les exceptions:
Je vous avais parlé d'exceptions au-dessus. Nous y voilà!
Ces exceptions sont des conditions qui ne contiennent pas de if au debut. Elle ne terminent pas non plus par ":". Ces conditions peuvent être utilisées si vous voulez un code moins long et si vous n'avez pas de else ensuite.
Exemples:
player's health is 10 (équivaut à if player's health is 10: )
experience of player is greater than 16 (équivaut à if experience of player is greater than 16: )
player is flying (équivaut à if player is flying: )

Les actions

Les actions sont ce qui va être fait lorsque l’événement à été produit et après les éventuelles conditions (voir entre 2 conditions).
Elles vont souvent utiliser les acteurs de l'action comme le joueur l'ayant fait, le type de bloc cassé etc...
La liste des actions est ici: http://njol.ch/projects/skript/doc/effects
Exemples d'actions:
push the player upward at speed 10 #Éjecter le joueur a une vitesse de 10 vers le haut
cancel event #Annuler l'événement
teleport victim to attacker #téléporter la victime a l'attaquant

Un petit point sur l'action "cancel event":
Cette action permet d'annuler TOUS ce que l’événement vas faire
Exemple:
Code:
on break:
    cancel event

Ici quand un bloc va être cassé, tous va être annulé!
Donc ça nous fait:
- Le bloc va être reposé
- Les dégâts subit par l'outils du joueur va être annulé
- Les drops effacé
etc...


Un exemple de Skript pour ces 3 étapes:

Code:
on join: #Evennement
    if player has permission "skript.exemple": #Condition
        if player's world is "survie": #Condition
            send "&aBon jeu dans le monde survie!" to player #Action
        else if player's world is "gateau": #Condition
            send "&aBon app dans le monde gateau!" to player #Action
        else: #Condition non verifiée
            kill the player #Action
            player is op #Condition!!!!
            send "&cPardon monsieur l'admin!" to player #Action

Les boucles (ou loops):

Je vais parler ici des boucles. Ces boucles permettent de tester toutes les valeurs pour la boucle souhaitée.
Exemple:
loop all players: #tester tous les joueurs
loop all entities in world "hell": #tester toutes les entités dans le monde "hell"
loop all items in inventory of player: #tester tous les items dans l'inventaire du joueur

Les boucles finissent elles aussi par ":" et donc la ligne suivante aura 1 TAB en plus
Lorsque vous avez déclaré une boucle, une nouvelle "expression" va être créée nommé souvent "loop-%type de loop%" a part pour les variables mais on en parlera plus tard.
Exemples:
Code:
loop all players:
    if loop-player is in world "jean-pierre":
        send "THUG LIFE!" to loop-player #Je suis désolé j'ai plus d'idées rationnelles :/
loop all items in player inventory:
    if loop-item is diamond pickaxe:
        set loop-item to air
        send "Adieu la pioche en diamant de %player% MOUAHAHA &kkkkkkkkk" to player


Les commandes:

Vous déclarez une commande à la place d'un événement comme ceci:
Code:
command /nomdelacommande:
    trigger:

Le trigger est a partir de l'endroit où les conditions et actions commenceront. Avant vous pouvez mettre les descriptions, qui peut les exécuter etc... Sachez que ceci n'est pas obligé d'être mis, perso je ne les met pas ^^
Voici ce que vous pouvez mettre avant le trigger:
- description: La description de ce que fait la commande
- usage: Comment la commande doit être utilisée, ex: /nomdelacommande <arguments>
- permission: les.permissions.necessaires
- permission message: Le message affiché si le joueur n'a pas la permission
- executable by: Qui peut exécuter la commande: players, console OU players and console
- aliases: Les abréviations pour exécuter la commande, ex: /c

Pour les arguments vous devez ajouter <type d'argument> après le "command /nomdelacommande:"
Exemple:
Code:
command /abcdef <text> <int>:
    trigger:

Dans les conditions et actions vous allez devoir utiliser "arg 1/2/3..." ou "%argument 1%" si vous voulez l'inclure dans une variable comme dans un message par exemple
Exemple:
Code:
command /coucou <player>:
    trigger:
        send "&bCOUCOU %argument 1%" to arg 1

Les variables:

Il existe en Skript 3 types de variables:
- Les variables temporaires
- Les variables enregistrées
- Les groupes de variables

Les variables sont définies et utilisées entre des {}. Elles peuvent également contenir des ".".
Exemple:
{coucou}
{variable}
{skript.test}

Les variables contiennent une valeur (a part pour les groupes) et peuvent être changées ou implémentées dans un texte ou une condition
Une variable temporaire contient un _ avant le nom. Cette variable ne sera pas sauvegardée et si 2 même événements sont produits en même temps, même si les variables utilisées ont le même nom, elles pourront être différentes. Ces variables seront également supprimées à la fin de l'événement.
Exemple:
{_coucou}
{_variable}
{_skript.test}

Les variables enregistrées ou fixes sont sauvegarder dans une base de données et peuvent être réutilisées ou changées à n'importe quel moment.
Exemple:
{coucou}
{variable}
{skript.test}

Pour finir nous avons les groupes de variables, ce sont des groupes contenants plein de variables. Avec une boucle, nous pouvons tester toutes les variables contenues dans ce groupe. Ils sont définis avec "::" après le nom
De plus, si vous mettez "::*", c'est le groupe en entier qui est sélectionnée et si vous mettez "::%nom d'une variable%", ce sera juste la variable avec ce nom dans ce groupe qui sera sélectionnée.
Ce groupes peuvent contenir n'importe quelle données aussi, comme des noms de joueur, des UniqueUID, des entités, des localisations...
Exemple:
{list.skript::*}
{joueur.op::*}

Si vous utilisez une variable dans du code, elle sera remplacée par la valeur la contenant:
Exemple:
if {time.player} is greater than 45:

Ici {time.player} sera remplacée par la valeur la contenant.
Autre exemple:
teleport player to {location.spawn}

Si la variable {location.spawn} est bien une localisation, ça marchera. Si la variable est imaginons 5, rien ne se passera car une joueur ne peut pas être téléporter a un nombre
Les variables peuvent également être utilisées dans les textes et elles seront remplacées par leur valeur mais elles devront être contenues entre des %.
Exemple:
broadcast "%player% a joué %{time.%player%}%"

Pour éditer une variable, vous utiliserez ceci:
- set {var} to location of player #La variable sera la position du joueur
- add 5 to {var} #On ajoutera 5 à la variable
- remove 9 from {var} #9 sera retiré de la variable
- clear {var} #La variable sera effacée


Les événements on death et on damage:

Dans ces deux événements, il n'y aura pas de player mais un "attacker" et une "victim"
attacker est celui qui tue ou qui fait les dégâts et victim est celui qui meurt ou reçoit les dégâts


Dernier point sur les textes et les variables:

Pour utiliser un nom ou valeur contenu dans les acteurs de l'event (nom de joueur, type de bloc cassé...) dans un texte ou le nom d'une variable, vous devrez mettre des % autour de la valeur voulu:
Exemples:
broadcast "%player% est gentil"
broadcast "%player% a cassé un(e) %event-block%"
add 1 to {time.%player%}
Les boucles pour les variables:

Je vais vour apprendre ici à faire une boucle pour un groupe de variable (donc qui fini par ::*). Voici la démarche à entreprendre:
Vous devez mettre "loop {ma.variable::*}:". Attention! Il faut bien que ce soit ::* à la fin et non ::variable ou autre.
Ensuite vous obtiendrais 2 valeurs pour la boucle nommées "loop-index" et "loop-value".
Loop-index est l'index de la boucle. Par exemple, si votre boucle en ai à la 20ème variables du groupe, loop-index vaudra 20.
Loop-value est la valeur contenu dans la variable testée. Si vous en êtes à la 20ème variable, vous allez obtenir la valeur de la 20ème variable.

Exemples de Skript:

Ce Skript permet de faire un casino. Pour qu'il marche il faut faire d'abord "/casino give" et cliqué successivement sur les 3 blocs qui changeront puis de mettre un bouton avec au-dessus un panneau avec
"&a[CASINO]" (un plugin de couleur sur les panneaux est necessaire)
""
"Cliquez pour"
"jouer"

Et en dessous un panneau avec:
"&a[CASINO]"
""
"Pret"
""

Code:
command /casino <text>: #Commande pour give les items pour indiquer les blocs
    trigger:
        if player is op:
            if arg 1 is "give":
                give 1 glowstone dust named "&aBloc 1 casino" to player
                give 1 glowstone dust named "&aBloc 2 casino" to player
                give 1 glowstone dust named "&aBloc 3 casino" to player

on rightclick on button: #Quand on clic sur le bouton
    if block above event-block is sign: #Début de la verification des panneaux
        line 1 of block above event-block is "&a[CASINO]"
        line 3 of block above event-block is "Cliquez pour"
        line 4 of block above event-block is "jouer"
        if block 1 under event-block is sign:
            line 1 of block under event-block is "&a[CASINO]"
            if line 3 of block under event-block is "&kaaaaaaa":
                send "&cUne partie est déjà en cours!&r" to player
                stop
            else: #Fin de la vérification des panneaux
                if {points.%uuid of player%} is greater than 99: #Si le joueur a assez de points
                    set line 3 of block under event-block to "&kaaaaaaa" #Mettre en ligne 3 du panneaux en dessous: "&kaaaaaaa"
                    remove 100 from {points.%uuid of player%} #Enlever 100 points au joueurs
                    set {_loop} to a random number between 10 and 30 #Début de la boucle qui change les blocs
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block1} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block1} to red wool
                            else:
                                set block at {casino.block1} to green wool
                        chance of 33%:
                            set block at {casino.block2} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block2} to red wool
                            else:
                                set block at {casino.block2} to green wool
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block1} is red wool:
                        set {_1} to 1
                    if block at {casino.block1} is blue wool:
                        set {_1} to 2
                    if block at {casino.block1} is green wool:
                        set {_1} to 3
                    set {_loop} to a random number between 10 and 30
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block2} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block2} to red wool
                            else:
                                set block at {casino.block2} to green wool
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block2} is red wool:
                        set {_2} to 1
                    if block at {casino.block2} is blue wool:
                        set {_2} to 2
                    if block at {casino.block2} is green wool:
                        set {_2} to 3
                    set {_loop} to a random number between 10 and 30
                    loop {_loop} times:
                        chance of 33%:
                            set block at {casino.block3} to blue wool
                        else:
                            chance of 33%:
                                set block at {casino.block3} to red wool
                            else:
                                set block at {casino.block3} to green wool
                        wait 2 ticks
                    if block at {casino.block3} is red wool:
                        set {_3} to 1
                    if block at {casino.block3} is blue wool:
                        set {_3} to 2
                    if block at {casino.block3} is green wool:
                        set {_3} to 3 #Fin des boucles qui change les blocs
                    if {_1} is {_2}: #Verification si les blocs 1 et 2 sont identiques
                        if {_2} is {_3}: #Verification si les blocs 2 et 3 sont identiques (par conséquent les blocs 1 et 3 sont identiques)
                            send "&aVous avez gagné 750 points!" to player
                            add 750 to {points.%uuid of player%} #Ajout des points
                        else:
                            send "&cDommage vous avez perdu..." to player
                    else:
                        send "&cDommage vous avez perdu..." to player
                    set line 3 of block under event-block to "&aPrêt"
                else:
                    send "&cVous n'avez pas assez de points pour jouer!&r"

on rightclick holding glowstone dust: #Event qui permet de definir les blocs
    if name of player's tool is "&aBloc 1 casino":
        set {casino.block1} to location of clicked block
        clear player's tool
    if name of player's tool is "&aBloc 2 casino":
        set {casino.block2} to location of clicked block
        clear player's tool
    if name of player's tool is "&aBloc 3 casino":
        set {casino.block3} to location of clicked block
        clear player's tool

Exercices et TP

Exercice 1: Essayez de savoir à quoi sert ce Skript (Facile!)

Code:
on craft:
    if event-item is diamond pickaxe or diamond shovel or diamond sword or diamond hoe or diamond axe:
        chance of 33%:
            give 1 diamond to player
            send "&aVous avez un diamant dont vous n'avez pas eu besoin pour votre craft!" to player

Réponse:
Il y a 1/3 pour que lors du craft d'un outils en diamant, le joueur récupère 1 diamant

Code:
on craft: #Evévenement: lors du craft
    if event-item is diamond pickaxe or diamond shovel or diamond sword or diamond hoe or diamond axe: #Si l'item crafté est en diamant
        chance of 33%: #33% de chance (donc 1/3)
            give 1 diamond to player #Donner 1 diamant au joueur
            send "&aVous avez un diamant dont vous n'avez pas eu besoin pour votre craft!" to player #Envoyer le message au joueur

Exercice 2: Créez ce Skript: (Facile!)
Lors d'un clic droit sur de l'herbe, si la faim du joueur n'est pas au max ça lui redonne 1 barre de faim et le bloc cliqué devient de la terre

Réponse:
Code:
on rightclick on grass: #Evénement clic droit sur de l'herbe
    if player's food level is not 10: #Si la faim du joueur n'est pas à 10 (donc le maximum)
        set player's food level to player's food level + 1 #Ajouter 1 barre de faim
        set clicked block to dirt #Le bloc cliqué devient de la terre
Merci de ton tuto il est très bien, mais je n'arrive pas a faire en sorte sur mon serveur qu'un métier qui coûte 1000 par exemple, et bah il faudrait qu'on est 1000 minimum pour l'acheter, mais la même si une personne a 0 elle peut tout acheter
 

Nashoba04

Développeur
21 Décembre 2013
87
22
111
35
Merci de ton tuto il est très bien, mais je n'arrive pas a faire en sorte sur mon serveur qu'un métier qui coûte 1000 par exemple, et bah il faudrait qu'on est 1000 minimum pour l'acheter, mais la même si une personne a 0 elle peut tout acheter
Tu dois ajouter une condition:
Code:
if player's balance is greater than 999:
    #Le joueur a assez d'argent
else:
    #Le joueur n'a pas assez d'argent
 

AstroTiger_

Bucheron
27 Mai 2017
48
0
11
22
Tu dois ajouter une condition:
Code:
if player's balance is greater than 999:
    #Le joueur a assez d'argent
else:
    #Le joueur n'a pas assez d'argent
Je viens d'éssayer et sa ne marche pas, je dois mal faire un truc, tu aurait skype pour m'aider, ou faire un any desk ?
 

Dead700

Aventurier
11 Juin 2017
3
0
1
bonjour yatile pouver vous m'aider su un skript de chance???
 
Dernière édition: