Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 16/04/12 23:12 Sujet du message: les commandes chat string
Comment faire simplement un système de commande chat string efficace ?
Déjà voila comment je défini une commande : -<NomDeLaCommande> <ParamêtreOptionnelRattachéALaCommande>
Dans mon exemple les commandes seront détectées par le caractère "-". Vous pouvez très bien le changer à votre guise. De plus, afin de faire simple, ce système ne permettra de gérer que des commandes contenant un seul paramètre.
Remarque : Cet event se déclenchera même si le caractère "-" n'est pas le 1er de la chaîne. On peut rajouter une sécurité en mettant la condition suivante :
Gui:
Trigger:
(Substring((Entered chat string), 1, 1)) Egal à (==) -
I/ Le système de lecture de chat string
On se place dans un trigger avec l'event suivant :
En GUI :
Gui:
Trigger:
Joueur - Joueur X (Rouge) types a chat message containing - as Une sous-chaîne
Bon à savoir : : on ne peut pas utiliser l'event chat avec TriggerRegisterPlayerEvent, tout simplement parce que les fonctions qui sont censées donner les strings entrés en paramètre de l'event, retournent "null" de cette façon (oui c'est un bug).
Remarque : Pour que le trigger s'active à chaque message, il suffit de ne mettre une chaîne vide en event ("" en JASS).
Vous en mettez pour autant de joueur que vous le souhaitez, dans notre exemple c'est le joueur X qui pourra utiliser nos commandes.
Secret:
Bon et puis les emmerdeurs qui me diront que en jass c'est X-1 car le GUI commence à compter à 1 et le JASS à 0 je vous proute :p dans notre exemple le JASS et le GUI forment une parfaite harmonie
Bref, continuons :
Une fois votre event fait, il ne vous reste plus qu'à construire votre lecteur de chat string. Cela va être horriblement atroce super intéressant, car même si j'ai déjà fait ce système en JASS, je ne l'ai encore jamais fait en GUI et donc je vais bien me faire <grossièreté> bien se marrer
Donc, commençons par le GUI :
Pour lire la commande entrée par le joueur, nous avons besoin tout d'abord de définir quelques variables :
-Une qui contiendra le texte, afin de le manipuler plus facilement ;
-Une qui nous indiquera combien de caractère contient la commande.
Gui:
Trigger:
Set trigger_string = (Entered chat string) Set nb_car = (Length of trigger_string)
Voila qui est fait.
Ensuite, on commence par lire le nom de la commande. Pour cela, on fait une boucle qui va faire prendre comme valeur à une variable de type chaîne chaque lettre de la commande, et l'ajouter dans une autre variable chaine.
Cependant, comme il se peut que la commande contienne un paramètre, il faut également détecter le caractère " " qui sépare le nom de la commande et son paramètre. Donc, il faut faire une boucle qui possède 2 sorties :
-Une qui est «quand on a atteint le dernier caractère de notre commande» qu'on peut matérialiser par «un entier qui prend comme valeur de 2 à nb_car.»
-Et une autre qui est «Si car = " "»
Or en GUI il est impossible de créer une boucle autre que For. Il faut donc passer par un subterfuge. Vous l'aurez remarqué, on a un "Si" donc une condition. On va donc utiliser un If/then/else qui donnera comme valeur à notre variable d'incrémentation celle de nb_car + 1 afin de sortir de la boucle. Soit :
Gui:
Trigger:
For each (Integer i) from 2 to nb_car, do (Actions)
Boucle - Actions
Set car = (Substring(trigger_string, i, i))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
car Egal à
Alors - Actions
Set j = i Set i = (nb_car + 1)
Sinon - Actions
Set name = (name + car)
Set name = String( name ) as Minuscule
(Vous l'aurez vu, j'ai mis un "set j = i", j'vais vous expliquer après.)
Maintenant, il faut s'occuper de notre paramètre éventuel.
Même principe, on lit chaque caractère sauf qu'au lieu de démarrer à 2 on démarre là où l'on s'est arrêté.
Sauf que dans le cas où l'on a un paramètre, notre i a pris la valeur de nb_car + 1 donc on ne peut plus l'utiliser pour continuer (vous verrez en JASS on pourra). C'est la raison du "Set j = i". On sauvegarde la position à laquelle on s'est arrêté, afin de continuer dans une autre boucle comme si de rien n'était. On a donc :
Gui:
Trigger:
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
car Egal à
Alors - Actions
For each (Integer i) from (j + 1) to nb_car, do (Actions)
Boucle - Actions
Set car = (Substring(trigger_string, i, i)) Set param = (param + car)
Sinon - Actions
Set param = String( param ) as Minuscule
Bref, si on récapitule, à la fin vous devez obtenir :
Gui:
Trigger:
Actions
Set trigger_string = (Entered chat string) Set nb_car = (Length of trigger_string)
For each (Integer i) from 2 to nb_car, do (Actions)
Boucle - Actions
Set car = (Substring(trigger_string, i, i))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
car Egal à
Alors - Actions
Set j = i Set i = (nb_car + 1)
Sinon - Actions
Set name = (name + car)
Set name = String( name ) as Minuscule
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
car Egal à
Alors - Actions
For each (Integer i) from (j + 1) to nb_car, do (Actions)
Boucle - Actions
Set car = (Substring(trigger_string, i, i)) Set param = (param + car)
Sinon - Actions
Set param = String( param ) as Minuscule
Remarque : Vous l'aurez peut être vu tout seul, mais pour que notre système prenne un paramètre supplémentaire, il suffit de rajouter une loop selon le même schéma. Cependant dans tout les cas on reste limité au nombre de loop que l'on fait, et à ce moment là si on ne veut plus être limité il existe une autre méthode qui consiste à créer un algorithme recommençant en boucle notre lecture de paramètre temps qu'il y a un " " avant le dernier caractère. Mais j'ai voulu faire simple et ne pas tutorialiser (mais oui ça existe) cette méthode.
Secret:
Voix off : C'est ça ouais, dit plutôt que tu ne sais pas faire !
ET D'OU TU ME SPOIL HEIN ??
(non non je ne développe pas de schizophrénie !)
(Si si)
Voici maintenant le même système en JASS (vous allez voir c'est pas pareil, ça roxx 10 fois plus !) :
Même principe, une lecture caractère par caractère dans des loop. Seule différence, en JASS on roxx et on peut sortir d'un loop sans passer par la case départ entier ! Le exitwhen de la loop fonctionne comme une condition, soit elle retourne true et on sort soit elle retourne false et on continue.
Ah et cette fois-ci, au lieu d'utiliser des variables globales on utilise des locales, c'est plus simple. Du coup on commence par définir chacune de nos variables.
Donc :
Jass:
local string trigger_string = GetEventPlayerChatString()
local integer nb_car = StringLength(trigger_string)
local string name = "" // si je ne met pas de valeur, je ne peux pas l'utiliser en mode addition.
local string car
local integer i
local string param = ""
set i = 2
loop
set car = SubString(trigger_string, i-1, i)
exitwhen (i > nb_car or car == " ") // vous voyez je définie 2 modes de sortie.
set name = name + car
set i = i + 1
endloop
set name = StringCase(name, false)
En plus, on a plus besoin de sauvegarder le i puisque cette fois-ci on garde sa valeur dans tout les cas !
Bref, on a plus qu'à lire le paramètre, de la même façon qu'en GUI presque :
Jass:
if car == " " then // pour pas qu'il lise quand il n'y a pas de paramètre.
loop
exitwhen i >= nb_car
set i = i + 1
set car = SubString(trigger_string, i-1, i)
set param = param + car
endloop
endif
set param = StringCase(param, false)
Et voila c'est terminé. Vous trouvez toujours que le GUI c'est plus simple que le JASS ?...
Voie off : Ba... Quand on est [Censure]très intelligent, et qu'on sent bon,[/Censure] on y peut rien !
D'OÙ TU ME CENSURES MAINTENANT ???
Remarque : Vous l'aurez notez, je reset mon name et mon param avec la fonction StringCase en jass et avec une autre fonction ayant le même effet en GUI. grâce à ça, si un joueur utilise le nom de la commande AvEc DeS MaJuScUlEs la fonction la reconnaitra toujours. Vous n'êtes pas obligé de le faire si cela ne vous intéresse pas, perso je considère que c'est pas très utile.
II/ Détection de commande.
Bon c'est joli d'avoir lu notre commande et éventuellement notre paramètre, mais maintenant faut s'en servir. Je vais donc vous montrer quelques exemples de détection de commande, c'est tout con en faite. Tout ce qu'il y a à faire c'est une condition par commande : vous vérifiez si name, votre variable qui contient le nom de votre commande, est similaire à tel ou tel nom de commande et exécutez ensuite vos actions.
Exemple GUI :
Gui:
Trigger:
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
name Egal à kick
Alors - Actions
For each (Integer A) from 1 to 12, do (Actions)
Boucle - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
Multiple Conditions Or - Any (Conditions) are true
Conditions
param Egal à (String((Integer A))) param Egal à (Substring((Name of (Player((Integer A)))), 1, (Length of param))) param Egal à Couleur_txt[(Integer A)]
Alors - Actions
Partie - Display to (All players) for 10.00 seconds the text: ((Name of (Triggering player)) + ( a kické + ((Name of (Player((Integer A)))) + de la partie.))) Partie - Defeat (Player((Integer A))) with the message: Vous avez été kické
Sinon - Actions
Sinon - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
name Egal à visibility
Alors - Actions
For each (Integer A) from 1 to 16, do (Actions)
Boucle - Actions
Visibilité - Destroy Visibility_AC[(Integer A)] Visibilité - Create an initially Activé visibility modifier for (Player((Integer A))) emitting Visibilité across (Entire map) Set Visibility_AC[(Integer A)] = (Last created visibility modifier)
Sinon - Actions
Je vous recommande fortement d'utiliser un bloc If/then/else par commande, afin que votre déclo soit plus aéré donc plus agréable à relire.
On a en premier une commande permettant de kick un joueur par 3 moyens différents :
-le slot (les valeurs qu'on retrouve en GUI de 1 à 12)
-la couleur, avec 1 variable à déploiement 12 qui se set quand la variable et le paramètre sont similaires
-le nom du joueur
En 2è on a un système de visibilité s'actionnant dans 16 régions. Hors contexte c'est pas très utile mais dans la map ça avait probablement son utilité x).
Exemple JASS :
Jass:
// premier block qui vérifie si le joueur a rentré comme name "aoa" ou "angleOfAttack, cette commande change l'angle d'attaque de la caméra du triggering joueur.
if (name == "aoa" or name == "angleOfAttack") and param != "" then
set angle = S2R(param)
call SetCameraFieldForPlayer(GetTriggerPlayer(), CAMERA_FIELD_ANGLE_OF_ATTACK, angle, 0.)
// un autre block, à la suite de l'autre. une nouvelle commande = nouvelle condition. celle ci règle le zoom de la caméra.
elseif (name == "cf" or name == "cameraField") and param != "" then
set trg_player = GetPlayerId(GetTriggerPlayer())
set hauteur = S2R(param)
if hauteur != 0. then
call SetCameraFieldForPlayer(Player(trg_player), CAMERA_FIELD_TARGET_DISTANCE, hauteur, 0.)
endif
//encore une autre commande qui s'occupe soit de kill soit de kick un joueur.
elseif name == "kill" or name == "kl" or name == "kick" or name == "kc" then
if GetTriggerPlayer() == Player(0) then
if param == "red" or param == "rd" then
set trg_player = 0
elseif param == "blue" or param == "be" then
set trg_player = 1
elseif param == "teal" or param == "tl" then
set trg_player = 2
elseif param == "purple" or param == "pe" then
set trg_player = 3
elseif param == "orange" or param == "oe" then
set trg_player = 5
elseif param == "yellow" or param == "yw" then
set trg_player = 4
elseif param == "green" or param == "gn" then
set trg_player = 6
elseif param == "pink" or param == "pk" then
set trg_player = 7
elseif param == "gray" or param == "gy" then
set trg_player = 8
elseif param == "lightblue" or param == "lb" then
set trg_player = 9
elseif param == "darkgreen" or param == "gn" then
set trg_player = 10
endif
endif
if param == "" then
set trg_player = GetPlayerId(GetTriggerPlayer())
endif
if name == "kill" or name == "kl" then
call KillUnit(udg_invisUnit_j[trg_player])
elseif name == "kick" or name == "kc" then
call CustomDefeatBJ(Player(trg_player), "Noob !")
endif
endif
Voila merci d'avoir suivi mon tuto.
Credits : @Vladadamm : Grâce à l'un de ses tutos non validé sur le système d'administration j'ai pas eu besoin de faire les exemples de commandes GUI moi même. Vous le verrez, j'ai copié collé ses triggers (s'pour ça que c'est mal présenté aussi).
@Maximaxou : Mon système est né de son fantastique système qui lui utilise l'algorithme dont j'vous ai parlé. (Il utilise d'autres trucs d'ailleurs qui permet un contrôle plus complet des commandes)
@Fulldragon : Bin oui quand même, les exemples de commandes JASS utilisées sont de moi. Elles sont présentes dans Slide of renewal 3 (qui n'est pas encore sorti).
map exemple : créée par moi.
slide of renewal 3 non protégé et non fini. _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Dernière édition par kungfu-sheep le 20/05/12 17:48; édité 7 fois
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 16/04/12 23:48 Sujet du message:
J'ai franchement la flemme de lire, mais bon si ca vient de Max cela ne peut pas être complètement mauvais.
Je voulais juste préciser que pour que le déclencheur se déclenche avec n'importe quel string il suffit d'utiliser un string vide ou un espace (ou les 2 sont valides) dans l'évènement, je ne m'en rappelle plus.
De même il me semble que le string en paramètre de l'event n'est pas sensible à la casse, alors que ça l'est quand on compare des strings.
Enfin on ne peut pas utiliser l'event chat avec TriggerRegisterPlayerEvent, tout simplement parce que les fonctions qui sont censés donner les strings donnés en paramètre de l'event, retournent "null" de cette façon. (oui c'est un bug)
Il faut impérativement utiliser TriggerRegisterPlayerChatEvent pour que celles ci fonctionnent correctement. _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 16/04/12 23:57 Sujet du message:
Troll-Brain a écrit:
J'ai franchement la flemme de lire, mais bon si ca vient de Max cela ne peut pas être complètement mauvais.
Ouais enfin bon tu prends le système de max, tu enlèves le côté hyper puissant, sa rigueur sans équivaux, son infaillibilité et tu obtiens mon système :p
Non plus sérieusement j'ai juste repris la base de son système : la lecture des chaines de caractères. Donc en effet le système en lui même est plus que correct quand on en a une utilisation basique pour des commandes standards.
Troll-Brain a écrit:
Je voulais juste préciser que pour que le déclencheur se déclenche avec n'importe quel string il suffit d'utiliser un string vide ou un espace (ou les 2 sont valides) dans l'évènement, je ne m'en rappelle plus.
je rajoute
Troll-Brain a écrit:
De même il me semble que le string en paramètre de l'event n'est pas sensible à la casse, alors que ça l'est quand on compare des strings.
j'ai pas compris ce qui est rouge.
Troll-Brain a écrit:
Enfin on ne peut pas utiliser l'event chat avec TriggerRegisterPlayerEvent, tout simplement parce que les fonctions qui sont censés donner les strings donnés en paramètre de l'event, retournent "null" de cette façon. (oui c'est un bug)
Il faut impérativement utiliser TriggerRegisterPlayerChatEvent pour que celles ci fonctionnent correctement.
je rajoute aussi, c'est bon à savoir. _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 17/04/12 23:06 Sujet du message:
ah oui en effet j'viens de comprendre.
je sais pas pour ce qui est de l'event, mais dans la comparaison je suis d'accord.
comme l'event dans le cas présent capte un "-", on a pas de problème de maj. _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 17/04/12 23:47 Sujet du message:
Je parlais bien entendu de façon générale.
Pour l'event le test est facile, je suis quasi certain que ce n'est pas sensible à la casse, mais comme je ne peux pas tester je n'affirme rien. _________________
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
Posté le: 15/05/12 21:35 Sujet du message:
C'est bon pour moi.
Si vous avez des remarques, vous avez une semaine pour le signaler (conformément à l'article n.315b du code du forum). Passé ce délais, il sera mis en officiel. _________________
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
Posté le: 16/05/12 19:13 Sujet du message:
C'est vrai que ce serait sympa de rajouter une fonction comme ça.
J'ai pas testé le StringExplode de Profet mais y'a de toutes façons encore des erreurs dans sa librairie (j'ai juste vu que son RawCode2Int n'était pas fixé et qu'il y avait un "FW_SubString( s, ..., -1 )" douteux dans StringExplode) et c'est du vJass.
En jass, comme on ne peut pas renvoyer un string array, faudrait faire un truc dans ce genre là :
Jass:
local string s = "deux mots"
local string firstword
local string secondword
local integer strpos
set strpos = StringWord( s, 0 ) // Renvoi 4
set firstword = SubString( s, 0, strpos )
set secondword = SubString( s, strpos+1, StringWord( s, strpos+1 ) ) // StringWord renvoi 9
Sinon, j'avais oublié mais faudrait mettre une map exemple. _________________
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 16/05/12 19:20 Sujet du message:
Alors ton devoir en tant que modérateur et de mettre cette ressource au cimetière (je ne dois pas être le seul à jouer le rôle du méchant). _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 16/05/12 21:20 Sujet du message:
hé le tuto propose un système de commande simple ! j'l'ai dit...
pour la map exemple tu entends quoi ? une map où il y a juste le système de commande que l'on peut tester ? s'pas un problème j'mets sor3 à ce moment la. _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Inscrit le: 23 Aoû 2007 Messages: 7143 Sujets: 147 Spécialité en worldedit: le troll, le flood, la vulgarité, mon coeur balance Médailles: 2 (En savoir plus...)
Posté le: 16/05/12 21:32 Sujet du message:
J'aurais du citer la partie voulue mais je parlais de la ressource de Profet à vrai dire.
Je n'avais pas vu la phrase de Tirlititi où il parlait de faire une map d'exemple de ton tuto, en gros je croyais qu'il parlait uniquement de la ressource de Profet. _________________
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
Posté le: 23/05/12 15:11 Sujet du message:
Tuto passé en officiel.
Cependant, je ne te cache pas que l'intérêt d'une map exemple, c'est surtout de pouvoir copier/coller les déclencheurs GUI sans avoir à tout faire à la main...
Et si tu veux plonger le système dans une map plus grande, faut au moins que tu organises tes déclos pour qu'on trouve facilement le système de commande.
À ta place, j'aurais honte de montrer un travail inachevé et aussi bordélique dans un tuto . _________________
Inscrit le: 14 Avr 2011 Messages: 1846 Sujets: 119 Spécialité en worldedit: fonctions paramétriques, équation de mouvement.
Posté le: 23/05/12 15:40 Sujet du message:
j'ai pas autre chose... pi c'est une vieille version non jouable (je viens de tester) car j'ai perdu la dernière que j'avais faite (p'tit soucis au moment de reformater j'ai oublié de save :p)
sinon merci ^^ _________________
22:27:43<Seiraw> Bah y a deux genre de personnes
22:27:57<Seiraw> les soumis et les soumises
Inscrit le: 14 Oct 2009 Messages: 719 Sujets: 40 Spécialité en worldedit: Les bugs Médailles: 1 (En savoir plus...)
Posté le: 21/06/12 08:49 Sujet du message:
Jass:
loop
exitwhen i >= nb_car
set i = i + 1
set car = SubString(trigger_string, i-1, i)
set param = param + car
endloop
Pourquoi tu ne fais pas plutôt :
Jass:
set param = SubString(trigger_string, i - 1, StringLength(trigger_string))
Sinon dernièrement j'ai eu besoin de faire des lectures de paramètres, comme dans ton tuto, mais j'avais besoin d'en lire plusieurs. J'ai donc fait trois super fonctions :
Jass:
private function GetSpace takes string s, integer n returns integer
local integer i = 0
local integer j = StringLength(s)
local integer k = 0
local string sub
loop
exitwhen k == n or i == j
set sub = SubString(s, i, i + 1)
if sub == " " then
set k = k + 1
endif
set i = i + 1
endloop
if i == j then
return i
else
return i - 1
endif
endfunction
Cette première fonction donne à quel niveau de la chaîne de caractère s l'espace numéro n se trouve. A noter que c'est là où l'espace commence et non où il termine.
On peut ensuite l'utiliser pour faire ça :
Jass:
private function GetFunction takes string s returns string
return SubString(s, 1, GetSpace(s, 1)) //Le premier espace marque la fin de la fonction
endfunction
De même que pour lire des paramètres :
Jass:
private function GetParameter takes string s, integer n returns string
return SubString(s, GetSpace(s, n) + 1, GetSpace(s, n + 1))
endfunction
On donne le string s et ça nous renvoie le paramètre numéro n.
Étant donné que GetSpace renvoie la fin de la chaîne s'il n'y a pas d'espace, s'il n'y a aucun paramètre, GetParameter renverra juste null.
Bon il y a encore un petit soucis : si l'utilisateur met deux espace entre deux paramètres, ça bug :/.
Mais je pense que ça pourrait être bien de le rajouté. _________________
Toutes les heures sont au format GMT + 1 Heure Aller à la page 1, 2Suivante
Page 1 sur 2
Vous ne pouvez pas poster de nouveaux sujets dans ce forum Vous ne pouvez pas répondre aux sujets dans ce forum Vous ne pouvez pas éditer vos messages dans ce forum Vous ne pouvez pas supprimer vos messages dans ce forum Vous ne pouvez pas voter dans les sondages de ce forum