Introduction
Programmer des plugins, ça vous tente ? Vous devez avant tout, télécharger le logiciel AMXPluginCreator (par Virtual). Il n'est pas indispensable pour la création de plugins mais il facilite pas mal de chose (notamment la compilation). Petites indications: dans ce tutorial, seul le code SMA est écrit en bleu. Les choses importantes sont mises en rouge et les conseils ou astuces sont en vert. Dernière chose qui pourra vous être utile avant de commencer, c'est l'écriture des commentaires. En SMA, une ligne précédée de // n'est pas lue par le compilateur, elle vous sert juste de point de repère. Si vous souhaitez, écrire un long commentaire, vous devez encadrer votre texte de /* (au début) et de * (à la fin). Vous reconnaitrez facilement vos commentaires dans AMXPluginCreator étant donné qu'ils sont écrits en vert Les plugins - Chapitre 1 Sommaire:
CHAPITRE 1: Où démarre un plugin ? Un plugin s'initialise au lancement de chaque map. (Rappel: Vous devez déclarer les plugins que vous utilisez dans le "plugins.ini") La première procédure appelée est "plugin_init()". Vous la définissez avec le mot "public" devant. Exemple de la procédure d’initialisation du plugin "Admin RestartRound" : [color=blue] public plugin_init() { register_plugin("Admin RestartRound","0.9.2","f117bomb") register_concmd("amx_rr","admin_rr",ADMIN_LEVEL_F,"< nombre de restart > < delai entre chaque restart >") return PLUGIN_CONTINUE }
[/color] La procédure (block) est délimitée par des accolades. La fonction register_plugin permet d’indiquer à l’utilisateur le nom du plugin, sa version et son auteur. Toutes les chaines de caractères (type string: voir chapitre 3) sont à mettre entre guillemets. La fonction register_concmd enregistre une autre fonction qui sera appelée de n’importe quelle console. Décomposons : - "amx_rr" : c’est ce que le joueur pourra taper dans sa console- "admin_rr" : c’est la fonction appelée lorsque le joueur rentre cette commande- ADMIN_LEVEL_F : c’est un niveau d’accès (pour les admins) - "< nombre de restart > < delai entre chaque restart >" : c’est le texte affiché lorsque la commande n’est suivie d’aucun argument.
Le mot "return" peut être suivi d'une variable. C'est ce que renvoie la fonction après son éxécution. Ici, et ce sera souvent le cas, on met "PLUGIN_CONTINUE", ce qui veut dire que le plugin peut continuer son éxécution. Par question de convenance, on préfère placer cette procédure tout en bas du code. CHAPITRE 2: Fonctions et évènements. Il ne faut pas confondre une fonction avec un évènement. Un évènement fait appel à une fonction. Par exemple, un joueur qui fait un frag crée un évènement. Si vous souhaité déclencher une action pour cette évènement, vous devez faire appel à une fonction. Exemple: [color=blue] register_event ("DeathMsg","hs","a","3=1")[/color] Sans vouloir vous prendre la tête, voici une petite interro surprise: Laquelle/lesquelles de ces propositions est/sont une/des fonction(s) ? un/des évènement(s) ? - register_event - DeathMsg - hs
Réponse: - register_event est une fonction (et oui!), elle permet l'éxécution d'une autre fonction lors d'un évènement- DeathMsg est un évènement (quand un joueur meurt...) - hs est une fonction, elle est appelée lors de l'évènement SI la condition est respectée. Mais quelle condition ? "3=1", c'est un peu bizarre mais ça veut dire que le 3° argument doit être égal à 1. mouais...on va laisser ça de coté pour l'instant. "a" est un flag, on aura le temps d'en reparler plus tard.
Bon, différence entre fonction et évènement, c'est ok ? -> on passe à la suite. CHAPITRE 3: Les variables. Le passage incontournable...En effet, tous les programmes sans exception tournent grâce à des variables.
1) Les types
En sma, ce n'est pas très compliqué, vous allez devoir vous servir principalement de 4 "types":- integer : nombre entier (ex: 549)- float : nombre à virgule flottante (ex: 175,3492)- string : chaîne de caractères. C'est un tableau d'octets (ex: "St3AmEr" -> tableau de 7 octets).- booléen : 2 valeurs possibles uniquement "true" ou "false" (vrai ou faux)A noter: une valeur de type string est à mettre entre guillemets.
2) Définitions et affectations
Toute variable doit être définie avant d'être utilisée:
[color=blue]new score new players[/color][32][color=blue] new Float:flooding[/color][33]
"score" est un integer. La variable "players" est de type string de longueur 32 octets (tableau de 32 caractères). "flooding" est une liste de 33 nombres à virgules (dans ce cas, on préfère le mot liste au mot tableau).
Dans le code précédent, les variables sont définies mais aucune valeur ne leur est affectée. Il est possible d'affecter une valeur à une variable lors de sa définition (ce n'est pas obligatoire). [color=blue] new argent = 4750 new levels[/color][5][color=blue] = {3, 5, 7, 9, 10} new kills[/color][33] = {0,...}
Houla...mais qu'est-ce que c'est que ça ? Bon, on va y aller doucement: "argent" est un integer défini avec la valeur 4750 (prix de l'awp...) "levels" est une liste d'entiers. Ceux-ci sont placés entre accolades et séparés par des virgules. Veillez à ne pas dépacer le nombre d'integer que vous avez déclarés entre crochets ! (ici: 5). "kills" est aussi une liste d'entiers. Ceux-ci sont tous définis avec la valeur "0" donc pour éviter 33 répétitions, il est préférable de mettre des points de suspensions - après avoir indiquer la valeur d'initialisation. Il est possible de déclarer plusieurs variables sur une même ligne: [color=blue] new a,b,c,d new x=4, y=15, z=7 [/color]
3) Portée
Une variable peut rester en mémoire plus ou moins longtemps selon l'utilisation que vous voulez en faire. [color=red]Une variable déclarée dans une procédure est automatiquement détruite lorsque la procédure se termine.[/color] Plus généralement et plus simplement, considérez qu'une variable déclarée entre 2 accolades n'est valable que pour le code compris entre ces 2 accolades.
Pour qu'une variable reste en mémoire tout au long de l'éxécution du plugin, il faut la déclarer au tout début du code, avant même la première procédure. Celle-ci pourra être modifiée dans toutes les procédures mais elle ne sera détruite que lorsque le plugin se réinitialisera (changemap). Bon allez, il est temps de programmer un peu. CHAPITRE 4: Premier plugin On va commencer par un plugin simple. Celui-ci a pour but d'attribuer de la vie de façon aléatoire (entre 50 et 150 hp) lorsqu'un joueur tape dans le chat général le mot "randomhp". Le joueur peut donc gagner de la vie mais aussi en perdre...c'est un risque. Je sais ce que vous pensez: "c'est quoi ce plugin à 2 balles ?" En fait, j'ai voulu faire court et simple à la fois, d'où ce résultat un peu tordu. Ca donne ça: [color=blue] #include public random_hp(id)
{ if (get_user_health(id)==100) set_user_health(id, random_num(50,150)) return PLUGIN_CONTINUE }
public plugin_init() { register_plugin("tuto001", "1.0", "St3AmEr") register_clcmd("say randomhp", "random_hp") return PLUGIN_CONTINUE } [/color]
On peut pas dire que c'est bien long. Bon bah comme d'hab, on décompose tout ça ligne par ligne (même si je pense que vous avez déjà tout compris).
Dans tous les plugins que vous ferez, il vous faudra mettre la ligne "#include " au début, c'est indispensable pour utiliser un bon nombre de fonctions. On fait appel ici au fichier "amxmod.inc" normalement situé dans le dossier "AMXPluginCreatorinclude".
Contrairement à la logique, on va d'abord regarder la fin avant de regarder le milieu: Vous reconnaissez la procédure que l'on a étudiée *Chapitre 1*, l'initialisation du plugin. Je m'arrête juste sur la fonction "register_clcmd". Cette fonction vous permet de définir les fonctions associées aux événements. Ici, "say randomhp" veut tout simplement dire qu'il faut taper "randomhp" dans le chat général pour que la fonction "random_hp" s'éxécute. Une fois l'événement accompli, c'est la procédure appelée qui prend le relais, on la définit comme suit: "public nom_de_la_procédure(argument1, argument2, ...)"[color=red]L'argument attendu ici est l'id du joueur. Il correspond à son "numéro" de connexion. Il ne dépasse jamais le nombre de slots du serveur. Un joueur prend immédiatement l'id disponible la plus petite (commence à 1).[/color]- "if": suivit d'une condition (cette condition doit être entourée de parenthèses)- "get_user_health(id)": renvoit l'état de la vie du joueur "id" (hp)- "==100": 2° argument de comparaison (si le joueur qui tape "randomhp" a 100 de vie alors...) - "set_user_health(id, value)": mets la vie du joueur "id" à la valeur "value" - "random_num(50,150)": génère un nombre entier aléatoire entre 50 et 150 (intervalle fermé)- "return PLUGIN_CONTINUE": continue l'éxécution du plugin
A noter: comme vous pouvez le constater, je n'ai pas mis d'accolades pour la procédure conditionnelle "if". En effet, n'étant suivi que d'une seule ligne, elle peut se passer de ces accolades. Chapitre 5: Fonctions utiles. Voici une liste de fonctions que l'on retrouve assez fréquemment dans les plugins. Elles ne sont pas difficiles à utiliser et en plus elles sont très pratiques. Lorsque id=0, cela concerne tous les joueurs. - console_print(id, message): Envoie un message dans la console du joueur "id".console_print(3, "Tu es ici dans la console") Affiche dans la console du joueur portant l'index 3, le message "Tu es ici dans la console". - client_print(id, type, message): Envoie un message au joueur "id". Ce message est écrit en bas à gauche de l'écran (au niveau du tchat) si le type vaut "print_chat". On verra d'autres types plus tard.client_print(0, print_chat, "Bienvenue à tous!") Affiche dans le tchat à tous les joueurs le message "Bienvenue à tous" - server_cmd(commande): Exécute une commande dans la console du serveurserver_cmd("mp_friendlyfire 0") Cette ligne permet de désactiver le friendly-fire (FF). - register_cvar(nomdelacvar, valeur): Enregistre une cvar et la valeur qui lui est attribué. Cette ligne est à mettre dans la première procédure appelée qui est...vous vous en souvenez pas ? "plugin_init()" En général, on utilise cette fonction pour une plus grande facilité d'utilisation pour le client, il a juste à changer cette valeur à cette endroit précis au lieu d'aller bidouiller dans différentes procédures du plugin.register_cvar("penalite_tk", "200") On imagine que le plugin a pour but de faire perdre de l'argent aux team-killers et que l'on initialise le nombre de dollars à 200. Ainsi, l'utilisateur peut facilement modifier la valeur à 493 s'il le désire. - get_cvar_num(nomdelacvar): Renvoie la valeur d'une cvar sous forme d'integer.new malus = get_cvar_num("penalite_tk") La variable "malus" est créée et initialisée à la valeur de la cvar "penalite_tk".
Ces quelques fonctions vous permettrons déjà de comprendre le fonctionnement de la plupart des plugins. Comme un programme autonome, un plugin reçoit une donnée (événement), effectue un traitement avec cette donnée (procédures, fonctions etc...) et renvoie un résultat (affichage à l'écran, sons, argent, vie etc...).
Chapitre 6: Les tests et les opérandes. Lorsque vous codez, un plugin ou un programme, vous avez besoin dans la quasi-totalité des cas de faire des tests. En effet, lorsque le client/joueur envoie une donnée au programme/plugin, celui-ci va faire quelque chose en respectant certaines conditions que vous lui aurez préalablement donné. Par exemple, lorsque'un joueur tape "amx_cvar sv_password cs-amx", le plugin va vérifier s'il a les droits pour effectuer le changement du mot de pass.
1) Le test "if-then-else"
C'est quoi ce charabia ? Et bien "if-then-else" représente la structure d'un test: - if : est suivi des conditions à respecter - then : est uivi du code à effectuer si elles sont respectées - else : suivi du code à effectuer si elles ne sont pas respectées
Il y a peu de langages dans lesquels on utilise le mot "then". En SMA par exemple, on le remplace par une accolade ouvrante "{", "then" est sous-entendu dans ce cas. Attention: Veillez à refermer un bloc en ajoutant "}" à la fin. C'est très important, si vous ne respectez pas cette convention, le plugin plantera et ne se compilera pas.
Exemples: [color=blue] if (get_user_health(id) == 1) { //si il reste 1 hp au joueur set_user_health(id, 100) // le remettre à 100hp }
[/color]
Voici un simple test que vous avez sans doute compris sans problème. Juste une petite précision: les accolades ne servent à rien ici mais pensez que si vous les enlevez, vous ne pourrez rajouter rien d'autres dans le bloc "if". Tant que vous n'avez pas fini un plugin, je vous conseille de les laisser.
[color=blue] if (get_user_health(id) == 1) { set_user_health(id, 100) } else if (get_user_health(id) == 69) { set_user_health(id, 250) client_print(id, print_chat, "Petit cochon, tu es en pleine forme apres un 69")} [/color] Ici, 2 tests s'enchainent, il n'y a que pour les valeurs 1 et 69 (de vie) que l'on effectue quelque chose. On pourrait rajouter une autre ligne comme suit: [color=blue] if (get_user_health(id) == 1) { set_user_health(id, 100) } else if (get_user_health(id) == 69) { set_user_health(id, 250) client_print(id, print_chat, "Petit cochon, tu es en pleine forme apres un 69") } else { client_print(id, print_chat, "Aucun bonus") } [/color] Et voilà, comme ça, on a écrit du code pour 1hp, 69hp, et tous les autres cas possibles. Maintenant, on peut virer quelques accolades inutiles, ce qui donne:
[color=blue] if (get_user_health(id) == 1) set_user_health(id, 100) else if (get_user_health(id) == 69) { set_user_health(id, 250) client_print(id, print_chat, "Petit cochon, tu es en pleine forme apres un 69") } else client_print(id, print_chat, "Aucun bonus") [/color]
2) Les opérandes
C'est bon ? Je ne vous ai pas trop embrouillé l'esprit ? J'espère parce que c'est pas fini. Il me reste encore à vous parler des opérandes (vous savez comme le "==" ?). Et bien les voici: - "==" : si les 2 expressions sont égales- "!=" : si les 2 expressions sont différentes- "<" : si la première expression est strictement inférieure à la seconde- ">" : si la première expression est strictement supérieure à la seconde- "<=" : si la première expression est inférieure ou égale à la seconde- ">=" : si la première expression est supérieure ou égale à la seconde
C'est bon ? Encore un ch'tit truc et c'est fini. A mettre entre 2 conditions:- "&&" : AND, les 2 conditions entourant ceci doivent être respectées- "||" : OR, l'une des 2 conditions doit être respectée
Ouf...ça y est, je voulais aussi vous parler des indentations mais je crois que je vais plutôt en parler au chapitre suivant, un chapitre cool... Chapitre 7: Les indentations. Ce chapitre ne va pas vous apprendre grand chose si ce n'est le mot "indentation". Même si vous n'en utilisez pas, c'est pas grave, votre plugin tournera quand même. Les "erreurs" d' indentations sont relevées par AmxPluginCreator mais n'empêche en aucun cas la compilation.
1) Besoin d'une définition ?
L’indentation consiste à introduire une ou plusieurs tabulations au début de certaines lignes d’un programme afin d’en améliorer la lisibilité. Vous devez vous dire que c'est pas très important ce truc-là. En effet, vous pouvez négliger l'indentation dans votre code si celui-ci ne dépasse pas les 20-25 lignes mais vous verrez qu'au delà ça devient vraiment illisible.
2) En quoi ça consiste ?
En gros, vous devez insérer une tabulation à chaque fois que vous faites un nouveau bloc. Cette explication est très simplifiée, je vais vous donner un exemple:
Voici un code qui n'est pas indenté: [color=blue] public exemple(id) { if (get_user_health(id) == 1) set_user_health(id, 100) else if (get_user_health(id) == 69) { if (get_user_armor(id) == 0) { set_user_health(id, 250) set_user_armor(id, 250) } } else client_print(id, print_chat, "Aucun bonus") } [/color]
Si vous arrivez à tout comprendre du premier coup d'oeil, vous êtes très fort.
Voici ce même code indenté: [color=blue] public exemple(id) { if (get_user_health(id) == 1) set_user_health(id, 100) else if (get_user_health(id) == 69) { if (get_user_armor(id) == 0) { set_user_health(id, 250) set_user_armor(id, 250) } } else client_print(id, print_chat, "Aucun bonus") } [/color]
C'est un chouilla plus clair, vous ne trouvez pas ?
Vous pouvez constater différents niveaux d'indentation. Je ne saurais trop vous expliquer autrement que par des exemples l'utilisation des indentations mais le but était juste de vous faire comprendre leur utilité. Dans le prochain chapitre, on retrouvera ce que vous avez appris dans celui-ci. Allez, "let's go team", c'est parti pour les boucles. Chapitre 8: Les boucles. Les boucles, c'est quoi? Les boucles sont des "petites procédures" éxécutées plusieurs fois de suite. Pour y trouver un intérêt, on s'arrange pour faire incrémenter, décrémenter (ou ce que vous voulez) une variable à chaque fois qu'on a fait un tour. Ainsi, en 2 lignes, on peut en faire 30.
Un conseil, soyez flémard en programmation. Si vous pouvez faire court, faites-le, ça permettra une optimisation du plugin en plus de la facilité/rapidité de lecture.
Il existe plusieurs types de boucles en programmation. En SMA, vous vous servirez principalement d'un seul d'entre eux: le "for". Je vous parlerai des autres types plus tard, ça sert à rien de faire du bourrage de crâne, ce qu'il faut, c'est comprendre le principe des boucles. La boucle "For"
Cette boucle a besoin d'une variable, d'une valeur de départ, d'une valeur de fin et d'une valeur d'incrémentation. Vous en faites pas, c'est très simple. Avec cette boucle, vous codez une déclaration, une affectation de variable et un test en même temps (on n'aurait pas vu ça dans les chapitres précédents?
Voici un exemple d'utilisation de la boucle "For": [color=blue] for(new i=0; i<10; i++) client_print(0, print_chat, "Bienvenue !") [/color]
Le message "Bienvenue !" est envoyé 10 fois de suite dans le tchat (je sais, ça n'a aucun intérêt) . On décompose:
- "new i=0": définition et affectation d'une variable, déjà vu dans le chapitre 3. - "i<10": la boucle s'effectue tant que la variable "i" est inférieure (strictement) à 10. - "i++": incrémente la variable "i".A noter: "i++" revient à faire "i=i+1" comme "steamer--" revient à faire "steamer=steamer-1".
Donc "i" va s'incrémenter jusqu'à atteindre une valeur limite, ici 9. La boucle s'effectuera 10 fois avec une valeur de "i" différente (0,1,2,3,....,9). Ici aussi, on retrouve l'absence d'accolades; et oui, le for n'est suivi que d'une seule ligne de code. Attention: les séparateurs dans la boucle "For" sont des points-virgules et non des virgules.
Voici un extrait de plugin ("Admin SlayAll"), un plugin qui selon moi ne présente aucun intérêt sauf peut-être celui de vous expliquer l'utilisation de la boucle "For":
[color=blue] new plist[/color][32][color=blue],pnum get_players(plist, pnum ,"a")
for(new i=0; i user_kill(plist[/color][color=blue]) [/color]
Et en plus, vous allez apprendre de nouvelles fonctions . Bon, la première ligne, je me passe de commentaires, vous l'avez comprise sans problème. En revanche la deuxième, un peu moins à mon avis. Allez, c'est parti pour les détails: [color=blue] get_players(plist, pnum ,"a") [/color]- "plist": c'est la liste (tableau de nombres) dans laquelle vont être indiqués les index des joueurs (mais pas n'importe lesquels...) - "pnum": renvoie le nombre de joueurs trouvés - "a": flag permettant de ne sélectionner que les joueurs en vie
Je détaillerai la fonction "get_players()" dans un autre chapitre. Pour l'instant, tout ce que vous avez à savoir, c'est qu'après cette ligne, "pnum" contient le nombre de joueurs en vie et "plist" l'index de chacun de ces joueurs.
On arrive à la boucle: [color=blue] for(new i=0; i user_kill(plist[/color][color=blue]) [/color]
Cette boucle va tuer un à un tous les joueurs (encore en vie, logique...) du jeu grace à la fonction "userkill(id)". Le tableau "plist" contient "pnum" éléments (index).
Mes deux exemples ne présentent aucune accolades mais si vous avez plus d'une ligne de code à répéter plusieurs fois, vous pouvez en ajouter.
Chapitre 9: L'affichage des variables
Travailler sur des variables, c'est bien mais parfois, on aura besoin de les afficher. Vous savez les messages colorés que vous voyez sur l'écran pour vous annoncer que vous êtes seul contre 4 terros . Ou bien les stats avec le nombre d'impacts, les dommages, la distance etc...
1) Les simples affichages de variables
On a déjà vu la fonction "client_print()" qui permettait d'envoyer un message à un joueur. On va s'en reservir mais cette fois-ci, en ajoutant des paramètres.Exemple: [color=blue] client_print(id,print_chat,"Le numero complementaire du premier tirage du loto de ce soir est le %d",num_comp) [/color]"%d" sera remplacé par la valeur de la variable "num_comp". Vous pouvez bien entendu afficher plusieurs variables dans une même chaine de caractères: [color=blue] client_print(id,print_chat,"Vous avez tué %s avec %d impacts pour finalement lui enlever %d de vie. Vous avez %f % de précision.", victim_name, nb_impacts, nb_dommages, floatrecision) [/color]
Récapitulatif:- %d : pour les nombres au sens large- %s : pour les chaines de caractères- %f : pour les nombres à virgules flottantes
Ce sont les principaux, vous faites tout avec. Après avoir vu comment fonctionnait l'affichage des variables, il vous faut trouver une manière sympa de les afficher. Le "client_print()", c'est bien sympa mais il y a mieux, heureusement... 2) Les "HUDmessages"
Ce sont tout simplement les messages colorés dont je vous parlais plus haut. Il faut 2 fonctions pour afficher un texte dans le HUD. La première définit tous les paramètres d'affichage du texte et la seconde affiche tout simplement le message à l'écran du client. Voici leur structure: [color=blue] set_hudmessage(red=255, green=0, blue=0, Float:x=0.05, Float:y=0.75, effects=0, Float:fxtime=6.0, Float:holdtime=6.0, Float:fadeintime=0.5, Float:fadeouttime=0.15, channel=1) [/color]
Décomposons:- red : indiquez une valeur entre 0 et 255 (couleur Rgb)- green : indiquez une valeur entre 0 et 255 (couleur rGb)- blue : indiquez une valeur entre 0 et 255 (couleur rgB)- x : je n'arrive pas à l'expliquer sans exemple: si x vaut 0.20, le texte débutera à 20% en partant de la gauche de l'écran. C'est "l'abscisse en pourcentage" si vous préférez.- y : pareil que x mais cette fois, c'est pour l'ordonnée par rapport au haut de l'écran. x et y peuvent prendre la valeur "-1.0". Cela permet de centrer le texte horizontalement (x) ou verticalement (y). C'est différent de x=0.50 ou y=0.50, attention... - effects : euh...vous allez laisser sur 0, ok ? - fxtime : mettez la même valeur que "holdtime" - holdtime : durée en secondes de l'affichage - fadeintime : effet qui affiche le texte progressivement (opacité 0% à 100%), vous indiquez ici une valeur en secondes représentant la durée de l'effet. - fadeouttime : comme pour le fadeintime mais pour effacer le message. Je vous déconseille de mettre des valeurs de fadeintime et de fadeouttime supérieures à 1.0, c'est juste pour faire un p'tit effet mais au delà de 1 seconde, ça peut être gênant. - channel : alors là, c'est très bizarre... vous définissez un texte pour un channel. C'est à dire que si vous affichez un texte qui doit durée 10 secondes (holdtime=10.0) avec le channel 2 et que 5 secondes après vous affichez un autre texte avec le même channel (2), le premier sera effacé et remplacé par le deuxième. euh...vous avez suivi...? Utilisez les channel 1 à 4 sachant que 1=5=9, 2=6=10, 3=7=11, 4=8=12. Bref, il existe 4 channels, donc 4 textes affichés en même temps au maximum.
Vous avez fait le plus dur, maintenant, il reste à afficher votre beau message coloré: [color=blue] show_hudmessage(0,"Les %s ont gagné %d rounds^n%s est le joueur qui a fait le plus de frags: %d", equipe, winrounds, bestplayer, nb_frags) [/color]
"Ouais d'accord, j'ai compris, c'est comme avec le client_print en fait. Mais c'est quoi ^n ?" C'est un saut de ligne, et oui, ça peut être pratique pour afficher clairement plusieurs informations en même temps avec le même channel
Alors...c'est pas si compliqué le SMA... Le prochain chapitre sera semblable au 5° ("Fonctions utiles"). Je vous donnerai une liste de fonctions bien pratiques pour faire des plugins. Chapitre 10: Fonctions utiles (2)
Comme dans le chapitre 5, voici une liste de fonctions qui pourraient vous être utiles. Certaines fonctions renvoient une valeur alors que pour d'autres, il vous faut indiquer une variable prédéfinie pour obtenir le "résultat" de la fonction. Certaines fonctions combinent les deux. Si c'est pas très clair, ne vous en faites pas, vous allez comprendre avec la liste suivante:
- get_user_name(id, name, size) : Stocke le pseudo du joueur "id" dans la variable "name" de longueur "size".new name[32][color=blue] get_user_name(victim,name,31) [/color] Enregistre le pseudo du joueur portant l'id "victim" (7 par exemple) dans la variable "name" préalablement définie.
- get_user_weapon(id,ammo,clip) : Renvoie l'ID de l'arme que le joueur "id" porte et stocke respectivement dans les variables "ammo" et "clip", le nombre de balles présentes dans le chargeur actuel et le nombre de balles présentes dans les autres chargeurs.new vweapon = get_user_weapon(victim,ammo,clip) "vweapon" est l'ID de l'arme, "victim" est l'ID du joueur, "ammo" est le nombre de balle dans le chargeur actuel et "clip" est le nombre de balles dans les autres chargeurs.
- get_weaponname(weaponid,weaponname,size) : Stocke le nom de l'arme d'ID "weaponid" dans la variable "weaponname" de longueur "size".new wpn[32][color=blue] get_weaponname(vweapon,wpn,31)[/color] Vous avez compris ? Alors, je ne développe pas.
- get_user_deaths(id) : Renvoie le nombre de morts du joueur "id".new vdeaths = get_user_deaths(victim) "vdeaths" est un nombre entier qui correspond au nombre de morts du joueur "victim".
- get_user_frags(id) : Renvoie le nombre de frags du joueur "id".new afrags = get_user_frags(attacker) "afrags" est un nombre entier qui correspond au nombre de frags du joueur "attacker".
- get_user_team(id, team, size) : Stocke le nom de l'équipe du joueur "id" (CT ou TERRORIST) dans la variable "team".new team[32] [color=blue] get_user_team(id, team, 31) client_print(id, print_chat, "Tu es un %s", team) [/color] Affiche: "Tu es un TERRORIST" par exemple. 6 nouvelles fonctions à connaitre par coeur parce que bientôt: interro ! Normalement, vous en avez appris 22 jusqu'à maintenant.
Vous commencez à savoir faire pas mal de p'tit truc en SMA. C'est bien si vous êtes allé jusque là sans lacher prise. Dans le chapitre suivant, on va parler des admins, ce sera un long chapitre mais bien utile... Chapitre 11: Les plugins avec les admins.
Beaucoup de plugins utilisent les droits d'admin. Vous aurez sans doute besoin de limiter l'éxécution d'une procédure à un joueur possédant des droits. Il existe plusieurs façons pour procéder au test permettant de savoir si un joueur est admin ou non mais je ne vous parlerai que de la plus simple et de la plus complète. Vous allez me dire: "il y a différents admins avec différents droits...", oui en effet, tous les admins, selon leur niveau d'accès, ne peuvent pas tout faire. On va donc, dans un premier temps, jeter un oeil sur ces différents niveaux.
1) Appel de procédures réservées aux admins.
On a déjà vu dans le tout premier chapitre la fonction "register_concmd()" mais sans détailler les différents niveaux d'accès. Cette fonction (située dans la procédure d'initialisation, je vous le rappelle) va transmettre des paramètres à la procédure qu'elle appellera; à savoir: l'ID du joueur, le niveau d'accès qu'il doit avoir et les indications sur l'utilisation de la commande. Rien que ça. Avant de voir en détail la fabuleuse fonction "cmd_access()", voici la liste des niveaux d'accès pour les admins:
a : ADMIN_IMMUNITY : L'immunité, le joueur ne peut être kické, banni, baffé, foudroyé etc...
b : ADMIN_RESERVATION : Le joueur peut squatter un slot réservé
c : ADMIN_KICK : Le joueur peut utiliser la commande "amx_kick"
d : ADMIN_BAN : Le joueur peut utiliser les commandes "amx_ban" et "amx_unban"
e : ADMIN_SLAY : Le joueur peut utiliser les commandes "amx_slap" et "amx_slay"
f : ADMIN_MAP : Le joueur peut changer de map via la commande "amx_map"
g : ADMIN_CVAR : Le joueur peut se servir de la commande "amx_cvar"
h : ADMIN_CFG : Pour la commande "amx_cfg"
i : ADMIN_CHAT : Le joueur peut utiliser "amx_chat" et toutes les commandes de chat
j : ADMIN_VOTE : Le joueur peut utiliser "amx_vote" et toutes les commandes de vote
k : ADMIN_PASSWORD : Le joueur peut modifier la cvar "sv_password"
l : ADMIN_RCON : Accès aux commandes du RCON m : ADMIN_LEVEL_A : Niveau A (pour des plugins supplémentaires)
n : ADMIN_LEVEL_B : Niveau B
o : ADMIN_LEVEL_C : Niveau C
p : ADMIN_LEVEL_D : Niveau D
q : ADMIN_LEVEL_E : Niveau E
r : ADMIN_LEVEL_F : Niveau F
s : ADMIN_LEVEL_G : Niveau G
t : ADMIN_LEVEL_H : Niveau H
u : ADMIN_MENU : Menu des accès
z : ADMIN_USER : Simple joueur (pas de droits)
Les lettres à gauche sont donc celles que vous indiquez dans votre fichier de config pour déclarer vos admins et les mots tels que "ADMIN_LEVEL_F" sont leurs équivalents dans la programmation du plugin. Ce sont donc ces-derniers que vous allez utiliser dans la fonction "register_concmd()".Exemple:[color=blue] register_concmd("amx_slay2","admin_slay",ADMIN_SLAY," 1-lightning|2-blood|3-explode")[/color]
Attention: la procédure "admin_slay" que vous appelez doit récupérer les paramètres que la fonction "register_concmd" a passé. Cela donne: [color=blue] public admin_slay(id,level,cid) {[/color]
Ce chapitre sera assez long comme ça pour que je vous épargne le type des paramètres passés à cette procédure. Utilisez toujours cette forme ("id,level,cid") et vous n'aurez pas de problèmes. Peut-être aura-t-on l'occasion d'en reparler -encore- plus en détails dans les chapitres suivants.
2) La fonction "cmd_access()"
Attention: cette fonction fait appel à l'include "amxmisc". Vous devez donc impérativement le déclarer en haut de votre plugin de la façon suivante: [color=blue] #include [/color]
Et alors là, rien de plus simple: vous effectuez un test au tout début de la procédure afin de savoir si le joueur est admin (avec les droits requis). S'il l'est, pas de problème, on continue l'éxécution, sinon, on l'arrête.Exemple: [color=blue] if (!cmd_access(id,level,cid,2)) return PLUGIN_HANDLED ...suite...[/color]
"cmd_access()" renvoie une valeur booléenne ("true" or "false"). Lors d'un test, on sous-entend que la comparaison se fait avec la valeur "true". Par conséquent, le fait de mettre "!" devant le fonction veut dire "Si c'est pas vrai...", en gros: "Si c'est faux". Donc voici 2 lignes qui suffisent à vérifier les droits d'un joueur. Je vois que le chapitre est bien chargé, je détaillerai donc la fonction "cmd_access()" avec ces paramètres dans un autre. En attendant, utilisez-là toujours de cette façon (avec le "2" en quatrième paramètre).
Bon et bah...maintenant faut digérer... Le prochain chapitre portera sur les optimisations de votre code. Chapitre 12: Les optimisations
Ce chapitre est vraiment ridicule par rapport au précédent, c'est juste histoire de vous montrer des p'tites choses sympas. Je vous l'ai dit dès le début de ce tuto: en programmation, il faut un code qui tourne vite et donc l'optimiser au maximum. Ne déclarez pas des variables à tout bout de champs et faites attention à l'utilisation des if-then-else, c'est pratique mais vous allez voir que, parfois, on peut les contourner.
1) Le switch
Peut-être qu'un jour, vous aurez besoin de traiter des choses différentes selon la valeur d'une variable. Jusqu'à présent, on utilisait le "if-then-else" pour faire ces tests. Cependant, lorsque l'on doit tester une variable avec plus de 2 ou 3 valeurs, ça devient vite lourd d'utiliser le "if". Il existe le "switch" pour vous simplifier la vie. Il effectue un bout de code en fonction de la valeur de la variable. Voici sa structure: [color=blue] switch(variable){ case 1:{ //code à éxécuter si "variable" vaut 1 } case 2:{ //code à éxécuter si "variable" vaut 2 } case 3: //code à éxécuter si "variable" vaut 3 } [/color]
Que c'est pratique, n'est-ce pas ? Ce sera plus lisible pour vous
2) (Pseudo=="St3AmEr") ? "Salut St3AmEr" : "Bonjour étranger"
J'ai pas trouvé comment intituler cette forme d'optimisation. Si le "Pseudo" vaut "St3AmEr", ce procédé renvoie la première option ("Salut St3AmEr") sinon il renvoie la deuxième ("Bonjour étranger").
Je ne m'étends pas trop sur ce chapitre, il était sensé être court et simple. Dans le chapitre suivant, on va développer ensemble un plugin permettant de jouer un son lorsqu'un joueur tue un admin. (c'est "mu". Chapitre 13: Création d'un plugin: AdminDeathSound
Dans ce chapitre, on va développer de A à Z un plugin qui a pour but de jouer un son lorsqu'un joueur tue un admin. C'est pas compliqué, vous allez voir, allez go: 1) Les étapes
Avant de se lancer tête baissée dans le code source du plugin, il faut d'abord réfléchir aux différentes étapes de celui-ci. Dans un premier temps, il faut récupérer l'événement "kill", c'est à dire à chaque fois qu'un joueur en tue un autre. Dans un deuxième temps, il faut identifier la victime: récupérer son ID.Troisième étape: effectuer un test sur cette victime afin de s'avoir si elle est admin du serveur ou non. Et enfin, quatrième étape: émettre un son sur le serveur.
2) Réalisation de la première étape
"Récupérer" un kill : une ligne dans le plugin_init [color=blue] register_event("DeathMsg","death_msg","a") [/color] Et voilà ! Dès qu'un joueur en tuera un autre, le plugin éxécutera la procédure "death_msg".- "DeathMsg": événement lié au kill- "death_msg": procédure appelée- "a": flag qui concerne un événements global
3) Réalisation de la deuxième étape
C'est qui qu'est mort ? Une fois dans la procédure "death_msg", il faut utiliser une fonction qui retournera l'ID du joueur qui vient de mourir. Pour cela, on utilise ceci: [color=blue] new victim_id = read_data(2) [/color]
Arf...trop dur, n'est-ce pas ? Sachez que si vous voulez récupérer l'ID du tueur, c'est "read_data(1)"
4) Réalisation de la troisième étape
La victime est-elle (était...) admin ? Pour le savoir, on va utiliser une "sous-fonction" de la fonction "cmd_access()", à savoir: "get_user_flags()". Voici la ligne de code qui nous intéresse: [color=blue] if (!(get_user_flags(victim_id)&ADMIN_LEVEL_A)) return PLUGIN_HANDLED [/color]
En gros, ça veut dire que "si la victime ne possède pas le niveau d'accès "m" (ADMIN_LEVEL_A) alors arrêter l'éxécution du plugin". Pour les joueurs sans droits, le code s'arrêtent ici. La suite de la procédure ne sera éxécutée que si la victime est admin.
J'ai mis le niveau d'accès "m" mais j'aurais pu mettre le niveau "a" (immunité), c'est à vous de voir quel type d'admin vous voulez identifier.
5) Réalisation de la quatrième étape
Et le son ? Et bien, c'est ici qu'on va le faire jouer. Encore une fois, nous allons retrouver une fonction que l'on a déjà vu dans les chapitres précédents: [color=blue] client_cmd(0,"spk misc/admindeath") [/color]
Ce code jouera le son "admindeath.wav" situé dans le répertoire "/sound/misc" et tous les joueurs l'entendront.
ATTENTION: Le son doit être précaché pour qu'il puisse être joué. Il faut donc pour ça, créer une nouvelle procédure: [color=blue] public plugin_precache() precache_sound("misc/admindeath.wav") [/color]
Le son pourra être téléchargé par tous les joueurs qui ne le posséderont pas déjà.
6) Plugin complet
Voyons ce que donne ce petit plugin au complet:[color=blue] #include
public death_msg() {
new victim_id = read_data(2)
if (!(get_user_flags(victim_id)&ADMIN_LEVEL_A)) return PLUGIN_HANDLED
client_cmd(0,"spk misc/admindeath")
return PLUGIN_CONTINUE }
public plugin_precache() precache_sound("misc/admindeath.wav")
public plugin_init() { register_plugin("AdminDeathSound", "1.0", "St3AmEr") register_event("DeathMsg","death_msg","a") return PLUGIN_CONTINUE } [/color] Bien entendu, pour que ce plugin fonctionne, vous devez nommer un fichier son "admindeath.wav" (8kHz).
On peut passer au chapitre suivant qui portera sur les événements. Je vous présenterai une liste d'événements pratiques. Chapitre 14: Quelques événements.
!!!!!!! EN CONSTRUCTION !!!!!!!
Date de création : 11/12/2005 @ 14:34
Dernière modification : 22/05/2008 @ 22:28
Catégorie : 5- Les plugins
Page lue 1894 fois
Prévisualiser la page
Imprimer la page
|