Pour commencer, on peut expliquer ça comme une structure capable de mémoriser pratiquement toutes les choses dans Wc3. Par exemple, vous pouvez sauvegarder des unités, des effets spéciaux, entiers, … Bref, pratiquement toutes les choses que vous voulez sauvegarder.
II/ Comment les utiliser ?
Premièrement, nous devons créer une table de hachage pour ensuite l’utiliser. Une fois créée, nous allons stocker cette table dans une variable pour pouvoir y faire référence à chaque utilisation.
Voici comment créer une table et la stocker dans une variable :
Gui:
Trigger:
Variable
Evénements
Map initialization
Conditions
Actions
Table de hachage - Create a hashtable Set hashtable = (Last created hashtable)
Maintenant que vous avez votre table de hachage, nous allons commencer à l’utiliser. Il faut savoir que chaque chose stockée dans une table est définie par 2 entiers. Ils n’ont aucune limite possible.
Voici un exemple pour stocker une variable :
Gui:
Trigger:
Stockage Evénements Conditions
Actions
-------- Sauvez la valeur 5 -------- Table de hachage - Save 5.00 as 0 of 0 in hashtable -------- Chargez la valeur dans la variable -------- Set valeurCharge = (Load 0 of 0 from hashtable) -------- Montrez la valeur 5 à tous les joueurs -------- Partie - Display to (All players) the text: (String(valeurCharge))
Comme vous pouvez le voir, une table de hachage est une structure qui permet de sauvegarder et de charger des choses. Il vous suffit de donner 2 entier « clefs » qui vous permettrons de retrouver plus tard la valeur sauvegardée. Dans l’exemple ci-dessus, nous aurions très bien pu sauvegarder du texte, du texte flottant, une unité, … à la place de la valeur 5. Toutes ces valeurs peuvent êtres stockées sans problème dans la même table de hachage.
III/ Pourquoi utiliser les Table de Hachage ?
En effet, vous allez me dire que tout ce que nous avons fait avant est possible à faire sans les tables. Je vous répondrais oui, mais c’est parce que vous ne savez pas encore que vous pouvez les utiliser avec les ID. Grâce à ça, nous allons pouvoir lier des donnés aux « handles » qui vont pouvoir servir plus tard. Nous allons voir ça tout de suite.
IV/ Handle ID ? Pourquoi c’est si puissant ?
Vous comprenez peut être dès maintenant comment on va utiliser les Tables et les ID. Mais laissez-moi vous expliquer.
Maintenant, dans Wc3, on est capable de déterminer un ID [C’est un entier] pour chaque chose, comme une unité. Chaque ID est unique.
Comme vous le savez maintenant, pour stocker une variable dans une table de hachage, il faut deux entiers. Et si par exemple l’un des deux était l’ID de l’unité qui est la cible d’un sort ? On pourrait alors stocker n’importe quelle information sur cette unité sans risque de conflits comme avec les variables à déploiement. Et ainsi faire d’un sort complexe qui requière beaucoup d’informations, un sort Multi-Instanciable [Que l’on peut lancer plusieurs fois en même temps].
V/ Exemples :
a) Sort de soin :
Pour bien comprendre le fonctionnement du système, nous allons faire des exemples ensemble. Nous allons commencer avec un sort qui va soigner 10 de vie par secondes pendant 10 secondes.
Bien, pour commencer, je vous conseil d’utiliser : "Unit - A unit Starts the effect of an ability" à la place de "Unit - A unit Begins casting an ability".
Gui:
Trigger:
Evénements
Unité - A unit Initie l'effet d'une compétence
Conditions
(Ability being cast) Egal à Heal
Actions
-------- Sauvez la valeur du temps [10] dans une table à la valeur (0, ID de l'unité ciblé) -------- Table de hachage - Save 10.00 as 0 of (Key (Target unit of ability being cast)) in hashtableHeal -------- Mettez l'unité ciblé dans le groupe de soin --------
Groupe unité - Add (Target unit of ability being cast) to unitHeal
Maintenant, faites un second déclencheur qui va effectuer les actions de soin :
Gui:
Trigger:
EffetH
Evénements
Temps - Every 1.00 seconds of game time
Conditions
Actions
Groupe unité - Pick every unit in unitHeal and do (Actions)
Boucle - Actions
-------- Chargez dans une variable le temps restant de soin de l'unité -------- Set tempsRestantHeal = (Load 0 of (Key (Picked unit)) from hashtableHeal)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
tempsRestantHeal Supérieur à 0.00
Alors - Actions
-------- Si le temps restant est supérieur à 0 alors ... -------- -------- ... effectuez le soin sur l'unité ... -------- Unité - Set life of (Picked unit) to ((Vie of (Picked unit)) + 10.00) -------- ... et enlevez 1 seconde au temps restant, puis resauvez la valeur dans la table -------- Table de hachage - Save (tempsRestantHeal - 1.00) as 0 of (Key (Picked unit)) in hashtableHeal
Sinon - Actions
-------- Si le temps restant est égal à 0 alors ... -------- -------- ... retirer l'unité du groupe de soin ... -------- Groupe unité - Remove (Picked unit) from unitHeal -------- ... nettoyez les tables pour ne pas perdre de mémoire -------- Table de hachage - Clear all child hashtables of child (Key (Picked unit)) in hashtableHeal
Bon, j’espère que vous comprenez tous ce qui est dans ce déclencheur. Le seul point obscur est la dernière ligne. Le « Table de hachage - Clear all child hashtables of child (Key (Picked unit)) in hashtableHeal ». Quand vous utilisez une table pour une unité spécifique, vous devez à la fin, mettre ce déclencheur pour nettoyer les éventuelles tables qui se seraient crées. C’est juste pour éviter de faire leaker votre déclencheur. Avec cette action, l’ID de l’unité est complètement nettoyée dans la table sélectionnée.
Avec cette solution, vous n’avez plus besoin d’utiliser de wait. Ainsi vous pouvez rendre votre sort MU.
Nous allons maintenant passer aux autres exemples, mais sachez qu’ils sont tous basés sur ce principe là, d’identification d’ID et de stockage de valeur dans l’ID de l’unité.
b) Sort de KnockBall :
Passons à un autre sort très connus et très apprécié, le « Knockball ». C’est un effet de recul de l’unité ciblé. C’est exactement le même principe que le sort de soin, sauf que cette fois, nous allons stocker plusieurs valeurs à l’unité et qu’au lieu qu’il y ait un soin, il y aura un effet de recul de l’unité.
Avant de commencer, je vous conseil de créer une nouvelle Table de Hachage. En effet, il y a la possibilité de réécrire sur une table déjà écrite. Et donc la possibilité d’avoir des conflits de sorts et d’unités si on fait tout sur la même table.
Voici les déclencheurs du sort de KnockBall :
Gui:
Trigger:
Evénements
Unité - A unit Initie l'effet d'une compétence
Conditions
(Ability being cast) Egal à Foot
Actions
-------- Sauvez l'angle de l'unité ciblée par rapport à l'unité ciblante -------- Set knockBallAngle = (Angle from (Position of (Triggering unit)) to (Position of (Target unit of ability being cast))) -------- Sauvez la distance de recul de l'unité [500] ... -------- -------- ... et multipliez là par la fréquence de chaque recul [0.40 s] -------- Set knockBallDistance = (500.00 x 0.40) -------- Sauvez le temps du KnockBall -------- Set tempsRestantKnockBall = 1.00 -------- Et ensuite, associé les variables à des valeurs différentes [0, 1, 2] dans la table [hashtableKnockBall] de l'unité [Key ...] -------- Table de hachage - Save knockBallAngle as 0 of (Key (Target unit of ability being cast)) in hashtableKnockBall Table de hachage - Save knockBallDistance as 1 of (Key (Target unit of ability being cast)) in hashtableKnockBall Table de hachage - Save tempsRestantKnockBall as 2 of (Key (Target unit of ability being cast)) in hashtableKnockBall -------- Et enfin, ajoutez l'unité au groupe du KnockBall --------
Groupe unité - Add (Target unit of ability being cast) to unitKnockBall
Voici le déclencheur qui va faire reculer toutes les 0.4 secondes l’unité ciblé :
Gui:
Trigger:
EffetK
Evénements
Temps - Every 0.04 seconds of game time
Conditions
Actions
Groupe unité - Pick every unit in unitKnockBall and do (Actions)
Boucle - Actions
-------- Chargez toutes les valeurs nécéssaires et déjà sauvé dans la table correspondante à l'unité -------- Set knockBallAngle = (Load 0 of (Key (Picked unit)) from hashtableKnockBall) Set knockBallDistance = (Load 1 of (Key (Picked unit)) from hashtableKnockBall) Set tempsRestantKnockBall = (Load 2 of (Key (Picked unit)) from hashtableKnockBall)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
tempsRestantKnockBall Supérieur à 0.00
Alors - Actions
-------- Si le temps restant est supérieur à 0 ... -------- -------- Associez la position de l'unité prise à une variable ... -------- Set positionPickedUnitK = (Position of (Picked unit)) -------- Déplacez l'unité prise à la position de l'unité prise, décallée de la Distance de Knockball avec l'Angle de KnockBall -------- Unité - Move (Picked unit) instantly to (positionPickedUnitK offset by knockBallDistance towards knockBallAngle degrees) -------- Sauvez le temps restant à la bonne place [2] en lui enlevant 0.04 s qui viennent de s'écouler -------- Table de hachage - Save (tempsRestantKnockBall - 0.04) as 2 of (Key (Picked unit)) in hashtableKnockBall -------- Supprimez la variable position de l'unité prise pour éviter les leaks -------- Custom script: call RemoveLocation( udg_positionPickedUnitK )
Sinon - Actions
-------- Si le temps restant est egal à 0 ... -------- -------- ... nettoyez les tables pour ne pas perdre de mémoire ... -------- Table de hachage - Clear all child hashtables of child (Key (Picked unit)) in hashtableKnockBall -------- ... retirer l'unité du groupe de KnockBall --------
Groupe unité - Remove (Picked unit) from unitKnockBall
Ce qui est important à retenir dans ce sort est l’utilisation des différentes “clefs”. En effet, vous aurez surement remarqué que seule la première clef pour la sauvegarde des valeurs change. La seconde clef reste tout le temps l’ID de l’unité en question. Mais la première peut changer et prendre n’importe quelle valeur. Donc vous pouvez sauvegarder un nombre infinis d’informations sur l’unité.
c) Système de résurrection de monstres :
Ce qui me fait passer à mon troisième exemple. On arrête avec les sorts et on passe à un système beaucoup utilisé dans les RPG. Il va nous permettre de sauvegarder l’emplacement de base de chaque créature pour ensuite la faire revivre à son emplacement de départ.
Voici comment procéder :
Gui:
Trigger:
Evénements
Temps - Elapsed game time is 0.10 seconds
Conditions
Actions
-------- Prenez toutes les unités de la map ... --------
Groupe unité - Pick every unit in (Units in (Playable map area)) and do (Actions)
Boucle - Actions
-------- Sauvegardez dans une variable la position de l'unité ... -------- Set positionPickedUnitD = (Position of (Picked unit)) -------- Sauvegardez le X de la position de l'unité à un endroit dans la table [0] ... -------- Table de hachage - Save (X of (Position of (Picked unit))) as 0 of (Key (Picked unit)) in hashtablePositionUnit -------- Sauvegardez le Y de la position de l'unité à un endroit dans la table [1] ... -------- Table de hachage - Save (Y of (Position of (Picked unit))) as 1 of (Key (Picked unit)) in hashtablePositionUnit -------- Supprimez la variable position pour enlever le leak possible -------- Custom script: call RemoveLocation( udg_positionPickedUnitD )
La seule remarque que l’on peut faire est que je passe par une variable pour sauvegarder la position de l’unité. C’est juste la méthode pour supprimer le leak.
Gui:
Trigger:
Dead
Evénements
Unité - A unit Meurt
Conditions
Actions
-------- Recréez une créature du même type que la mourrante à la position de celle qui vient de mourir ... -------- -------- ... grâce au chargement des coordonnées X [0] et Y [1] stockées dans la table -------- Set positionUnit = (Point((Load 0 of (Key (Triggering unit)) from hashtablePositionUnit), (Load 1 of (Key (Triggering unit)) from hashtablePositionUnit))) Unité - Create 1 (Unit-type of (Triggering unit)) for (Owner of (Triggering unit)) at positionUnit facing Orientation bâtiment par défaut degrees -------- Sauvegardez la position de l'unité dans sa propre ID [ID unique !] ... -------- Table de hachage - Save (X of positionUnit) as 0 of (Key (Last created unit)) in hashtablePositionUnit Table de hachage - Save (Y of positionUnit) as 1 of (Key (Last created unit)) in hashtablePositionUnit -------- Supprimez la variable pour éviter les leaks -------- Custom script: call RemoveLocation( udg_positionUnit )
Cet exercice est juste là pour bien vous faire comprendre que chaque créature à une ID unique. Alors n’oubliez pas de bien rechargez les positions à chaque création d'unités. Sinon la chaine va être brisée et les positions perdues !
d) Triple Kills :
Et enfin, le dernier exemple qui va nous permettre de compter les triples kill de suite. Avec toujours deux déclencheurs :
Gui:
Trigger:
Init Triple Kill
Evénements
Unité - A unit Meurt
Conditions
Actions
-------- Sauvez le temps entre 2 Kills maximum ... -------- Table de hachage - Save 5.00 as 0 of (Key (Killing unit)) in hashtableTripleKill -------- Augmentez la variable "compteurKill" de 1 pour l'unité tuante ... -------- Table de hachage - Save (compteurKill + 1.00) as 1 of (Key (Killing unit)) in hashtableTripleKill -------- Ajoutez l'unité tuante au groupe "TripleKill" --------
Groupe unité - Add (Killing unit) to unitTripleKill
Gui:
Trigger:
Effet Triple Kill
Evénements
Temps - Every 0.20 seconds of game time
Conditions
Actions
Groupe unité - Pick every unit in unitTripleKill and do (Actions)
Boucle - Actions
-------- Chargez les valeurs nécéssaire de l'unité prise ... -------- Set tempsRestantTripleKill = (Load 0 of (Key (Picked unit)) from hashtableTripleKill) Set compteurKill = (Load 1 of (Key (Picked unit)) from hashtableTripleKill)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
compteurKill Egal à 3.00
Alors - Actions
-------- Si la valeur du compteur de kill est égal à 3 ... -------- Partie - Display to (All players) the text: (Triple Kill for + (Name of (Owner of (Picked unit)))) -------- Supprimez l'unité prise du groupe, car elle a atteinds son but ... -------- Groupe unité - Remove (Picked unit) from unitTripleKill Table de hachage - Clear all child hashtables of child (Key (Picked unit)) in hashtableTripleKill -------- Remettez le compteur de Kill à 0 et sauvegardez la donnée dans la table -------- Set compteurKill = 0.00 Table de hachage - Save compteurKill as 1 of (Key (Picked unit)) in hashtableTripleKill
Sinon - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Si - Conditions
tempsRestantTripleKill Supérieur à 0.00
Alors - Actions
-------- Si la valeur du compteur de kill est différent à 3 et le temps restant est supérieur à 0 ... -------- -------- Enlever le temps passé [0,2 s] au temps restant -------- Table de hachage - Save (tempsRestantTripleKill - 0.20) as 0 of (Key (Picked unit)) in hashtableTripleKill
Sinon - Actions
-------- Si la valeur du compteur de kill est différent à 3 et le temps restant est egal à 0 ... -------- -------- Supprimez l'unité prise du groupe, car elle n'a atteinds son but ... -------- Groupe unité - Remove (Picked unit) from unitTripleKill Table de hachage - Clear all child hashtables of child (Key (Picked unit)) in hashtableTripleKill -------- Remettez le compteur de Kill à 0 et sauvegardez la donnée dans la table -------- Set compteurKill = 0.00 Table de hachage - Save compteurKill as 1 of (Key (Picked unit)) in hashtableTripleKill
Et voila, j’espère vous avoir éclairé les quelques points essentiels à connaitre pour manier les Tables de Hachage.
Il reste encore beaucoup de possibilités à exploiter. Mais c’est à vous de tester et d’avoir les idées. N’oubliez surtout pas que vous pouvez pratiquement tout sauvegardez dans les Tables.
- Quelle est la différence entre "Clear Parent Hashtable" et "Clear Child Hastable" ?
Clear Parent Hashtable : Nettoie toutes les valeurs de la table sélectionnée.
Clear Child Hashtable : Nettoie les valeurs liés à un ID de la table sélectionée.
Gui:
Trigger:
Actions
-------- Il n'y auras plus aucune valeur dans "tableTest" -------- Table de hachage - Clear tableTest -------- Il n'y auras plus aucune valeurs liées à la "triggering unit" dans "tableTest" -------- Table de hachage - Clear all child hashtables of child (Key (Triggering unit)) in tableTest
- Mais ton tutoriel n'est qu'en GUI ?! Comment je fais si je veux avoir plus d'informations sur les Hashtables en Jass et VJass ?
Tu vas simplement ici.
- C'est normal qu'il y ait des actions Table de Hachage qui fassent crasher le WorldEditor ?
Oui, certaines comme Save unitpool, Save EventId, ... font crasher WE car ce ne sont pas des types qui sont censés être disponibles dans le WE mais Blizzard y a pas pensé et a mis toutes les fonctions d'hashtable.
[Merci à rgf et Tirlititi]
- Pour save un "Type Unit", comment je fais ?
Il y a deux solutions :
- GUI : Il y a une fonction Gui qui permet de convertir Un texte en Type-unité : "Convert string to Unit-Type". Attention, il faut utiliser les noms en anglais.
Gui:
Trigger:
Actions Table de hachage - Save footman as 0 of 0 in hashtable Unité - Create 1 (Unit-type((Load 0 of 0 from hashtable))) for Joueur 1 (Rouge) at (Center of (Playable map area)) facing Orientation bâtiment par défaut degrees
- Jass : Vous avez une fonction à votre disposition.
Inscrit le: 30 Jan 2009 Messages: 669 Sujets: 56 Spécialité en worldedit: Faire des bug Médailles: 1 (En savoir plus...)
Posté le: 10/08/10 20:51 Sujet du message:
Pourquoi tu mets des "" à tutoriel ? ^^
Sinon, je vais relire et relire pour les fautes, mais plus tard.
Pour les "child", je suis entrain de me renseigner sur d'autres post. Mais ça me semble assez obscure ce que ça fait exactement. Mais bon, pour l'instant, savoir que c'est pour cleaner les hashtables est l'essentiel.
Je vous informe de ce que j'apprends d'autre !
Et oui, c'est très largement inspiré, mais ce n'est pas un recopiage bête et méchant ou une traduction parce que je suis mauvais en anglais. Je rajoute quand même deux exemples.
Et je sais que ceux qui font du Jass connaissent les Hashtables depuis longtemps, alors si y'en a qui savent ce que ça fait exactement. Ou qui on des explications ... Je suis preneur. _________________
Je trouve que c'est un bon tutorial pour débuter en Gui sur les hashtables. Pour ceux qui veulent se perfectionner, tu devrais mettre un lien vers celui de Bantas (qui lui est en Vjass). Avec ces deux, il y a une bonne vision d'ensemble.
Cette modification faite, je suis d'accord pour valider. _________________
Inscrit le: 21 Avr 2008 Messages: 1607 Sujets: 81 Spécialité en worldedit: Utiliser le travail des autres Médailles: 3 (En savoir plus...)
Posté le: 12/08/10 11:11 Sujet du message:
Je l'ai lu rapidement est j'ai compris donc à partir de là ça va. J'ai pas été choqué par les fautes mais il en reste quelques unes (nous aurions put).
Une petite remarque, pour le sort de knockback. Il vaut mieux utiliser un timer plutôt que l'évènement "every 0.04 seconds of game time"
Sinon c'est un tuto très pratique, merci. _________________
Inscrit le: 30 Jan 2009 Messages: 669 Sujets: 56 Spécialité en worldedit: Faire des bug Médailles: 1 (En savoir plus...)
Posté le: 20/08/10 17:08 Sujet du message:
Bon, je reviens d'une semaine et demie de vacance.
Donc je prend le temps de me poser, et je fait toutes les modifications nécessaires. Juste une question, ça apporte quoi de mettre un timer à la place de l'évènement "every 0.04 seconds of game time" ?
Edit : Quel est le lien pour le tuto de Bantas ? _________________
Inscrit le: 30 Jan 2009 Messages: 669 Sujets: 56 Spécialité en worldedit: Faire des bug Médailles: 1 (En savoir plus...)
Posté le: 24/08/10 10:47 Sujet du message:
C'est fait.
Peut être que les modérateurs pourrais effacer les messages qui suivent le tuto pour que ça soit plus facile de le lire ? Et ainsi ne laisser que les questions dites importantes qui ont eu une réponse sur le Topic. Nan ?
Et dans un forum parfait, on pourrais imaginer que chaque questions posées avec une réponse pourrais être intégrée dans le tuto dans une partie "questions" ou autre et les messages supprimé, comme ça, on garde des tuto clair, vachement lisible ! _________________
Ouais enfin c'est quand même pas facile de gérer ce genre de chose sachant que sélectionner les questions intéressantes qui ont obtenu une réponse satisfaisante n'est pas facile.
Dans un tutoriel parfait c'est l'auteur du tuto qui devrait faire ça lui même parce qu'il est le mieux placer pour savoir ce qui va faire avancer le tuto et ce qui n'est pas important :p _________________
Si vous recherchez quelque chose, il y a de très grandes chances que vous trouviez la réponse ici alors jetez y un oeil. Topic indispensable
Inscrit le: 09 Mar 2009 Messages: 1154 Sujets: 54 Spécialité en worldedit: Croâ ?
Posté le: 03/09/10 21:59 Sujet du message:
C'est normal qu'il y ait des actions Table de Hachage qui fassent crasher le WorldEditor ? Genre Save unitpool, ou Save EventId etc...
Et sinon, pour save un Type d'unité je fais comment ? _________________
Inscrit le: 21 Fév 2010 Messages: 1785 Sujets: 22 Spécialité en worldedit: La modestie Médailles: 1 (En savoir plus...)
Posté le: 03/09/10 22:44 Sujet du message:
Oué c'est normal, c'est pas des types qui sont censés être disponibles dans le WE mais Blizzard y a pas pensé et a mis toutes les fonctions d'hashtable.
Sinon, un type-unité est un entier donc je pense pas que tu puisse le stocker en GUI. En jass, ça ferait un truc du genre :
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