![](https://fr.metin2.dev/uploads/set_resources_42/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://fr.metin2.dev/uploads/set_resources_42/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
Hystos
-
Compteur de contenus
256 -
Inscription
-
Dernière visite
Type de contenu
Profils
Forums
Boutique
Calendrier
Messages posté(e)s par Hystos
-
-
Salut,
Il existe déjà une armurerie de ce type : https://fr.metin2.dev/topic/10854-thread/.
Après il peut y avoir des améliorations... Je pense particulièrement à l'architecture et à la portabilité du code, et également à optimiser un peu le tout (faire 5000 requêtes SQL c'est pas le top
Vive les jointures
)
-
Salut.
Pas besoin d'être expert en PHP pour te répondre, apache le fait déjà très bien :
Warning: mysql_connect(): Access denied for user 'thomas280599'@'node12.cluster1.easy-hebergement.net' (using password: YES) in /public_html/thomastribout/index.php on line 14
Les identifiants de connexions rentrés dans index.php aux lignes 14/15 ne sont pas corrects. Vérifie particulièrement le mot de passe.
-
Bonsoir,
Peut-être serait-il déjà un bon début de nous donner les codes utilisés ?
-
-
Désolé si c'est déjà fait, j'ai pas pris le temps de faire une recherche ^^
Je n'irai pas plus loin
Bonne soirée.
-
Je te mets en spoiler la liste non exhaustive des bonus (et qui date... mais reste valide).
Liste des bonus1 PV max
2 PM max
3 VIT
4 INT
5 STR
6 DEX
7 Vitesse d'attaque
8 Vitesse de déplacement
9 Vitesse du sort
10 Régénération des HP
11 Régénération EP
12 Chance d'empoisoner
13 Chance de provoquer un étourdissement
14 Chance de ralentir
15 Chance de faire une attaque critique
16 Chance de coup percant
17 Bonus contre les demi-humains
18 Bonus contre les animaux
19 Bonus contre les Orcs
20 Bonus contre les mystiques
21 Bonus contre les Mort-vivants
22 Bonus contre le Mal
23 Dommages absorbés par les PV
24 Dommages absorbés par les PM
25 Chance de prendre des PM aux ennemis
26 Chance de récupérer des PM lorsque vous touchez
27 Chance de bloquer un coup au Corps-à-corps
28 Chance d'éviter les flèches
29 Défensse à l'épée
30 Défensse à l'épée à 2 mains
31 Défensse à la dague
32 Défensse au gong
33 Défensse à l'éventail
34 Résistance aux flèches
35 Résistance au feu
36 Résistance à la lumière
37 Résistance à la magie
38 Résistance au vent
39 Chance de détourner une attaque au corps à corps
40 Chance de détourner une malédiction
41 Résistance contre le poison
42 Chance de restaurer les PM
43 Chance d'obtenir un bonus EXP
44 Chance de drop le double de YANG
45 Chance de drop le double d'objet
46 Augmentation des effets de la potion
47 Chance de réstaurer les PV
48 Immunise contre l'étourdissement
49 Immunise contre le ralentissement
50 Immunise contre les chutes
52 Portée de l'Arc
53 Valeur d'attaque
54 Défense
55 Valeur d'attaque magique
56 Défense magique
58 Max endurance
59 Bonus contre les Guerriers
60 Bonus contre les Ninja
61 Bonus contre les Sura
62 Bonus contre les Shamans
63 Bonus contre les monstres
64 Valeur d'attaque (%)
65 Défense (%)
66 EXP (%)
67 Chance de drop d'objet
68 Chance de drop pour un Yang
71 Dégats de compétences
72 Dégats moyen
73 Résistance contre les dégats de compétences
74 Résistance moyenne au dégats
76 Bonus CyberCafé EXP
77 iCafé Chance de trouver des yangs
78 Chance de parer une attaque Guerrier
79 Chance de parer une attaque Ninja
80 Chance de parer une attaque Sura
81 Chance de parer une attaque Shaman
-
Bonsoir,
Les "?", c'est vraiment un problème d'encodage. J'imagine que tu travailles sur Notepad++.
Si c'est le cas, il ne faut pas que tu cliques sur "Encoder en ..." mais sur "Convertir en ...".
-
Bonsoir,
Je te suggère d'aller faire un tour dans ta table item et de vérifier les données de l'objet généré par ton CMS.
Tu pourras ensuite faire les corrections qui s'imposent dans la requête SQL d'insertion.
-
Bien essayé valent76, sauf que ça ne satisfait pas au cahier des charges. Avec ton code, à chaque connexion, tu donneras l'objet en question au joueur et tu réinitialiseras le compteur. Ce n'est de toute évidence pas le but recherché. De plus, tu as fais des erreurs de syntaxes.
Ayant trouvé ce problème intéressant, je vous propose un petit article sur des pistes de résolution.
Dans toute la suite de ce message, je me baserai sur le fait que nous n'avons pas accès aux sources du jeu et que nos seuls outils sont les quêtes et la base de données.
La première chose à faire, c'est de mettre en lumière les principaux obstacles qui s'opposent à nous.
- Que se passe-t-il si le personnage possède plusieurs fois l'objet ?
- Que se passe-t-il si le personnage jette l'objet ? Que se passe-t-il si le personnage vend l'objet ou l'échange ?
Ensuite, on va essayer d'y répondre de la meilleure manière qui soit.
Je ne traiterai ici que le premier obstacle majeur en supposant que le personnage peut posséder plusieurs fois l'objet dans son inventaire mais que ce dernier ne peut pas être échangé, jeté, vendu ou mis dans l'entrepôt de compte (chose possible via l'antiflag).
Supposons que le personnage possède n fois l'objet (n supérieur à 1) dans son inventaire.
Posons objet_i , i allant de 1 à n, les n objets que le personnage possède dans son inventaire. Ils sont chacun identifiables par leur indice i (appartenant à l'intervalle d'entiers [|1, n|]).
Première difficulté : comment savoir quel est l'objet utilisé ?
En effet, on a l'habitude d'utiliser des syntaxes telles que ( when VNUM.use with ... begin ) qui permettent de capter l'événement d'utilisation d'un objet de vnum VNUM. Cependant, cela ne nous permet pas de savoir à quel objet on s'adresse. Comment individualiser notre objet ? En quoi est-il unique ?
Il y a plusieurs choix de réponse possibles. Le plus logique, le plus habituel et le plus efficace : son identifiant unique. Chaque objet du jeu est en effet lié à un identifiant unique qui permet d'accéder à ses caractéristiques particulières. On le retrouve notamment comme clé primaire de la table item (base player). Il se trouve qu'on a facilement accès à cet identifiant via la fonction item.get_id() qui s'applique justement à un événement d'utilisation d'un objet.
Nous pouvons donc désormais identifier chacun des n objets présents dans l'inventaire grâce à son identifiant unique que nous noterons pour la suite objet_id_i, i allant de 1 à n.
Intéressons nous maintenant plus spécifiquement à un objet d'indice k, k appartenant à l'intervalle d'entiers [|1, n|].
Deuxième difficulté : comment mettre en place la limite d'utilisation de cet objet ?
Là encore, il y a de nombreuses techniques possibles.
Fixons X le nombre de fois que l'objet peut être utilisé avant sa destruction.
1ere solution : event_flag personnalisé
Il nous faut un compteur, une variable numérique qui sera en quelque sorte liée à l'objet et que nous pourrons incrémenter ou décrémenter à souhait. Il se trouve que nous sommes capables de créer des variables numériques liées au personnage et de les gérer plutôt efficacement : les event flag.
Comment passer du personnage à l'objet ? Etant donné que par hypothèse l'objet ne changera pas de personnage, il est possible de transformer une variable du personnage en variable pour l'objet. On pourra choisir de nommer les variables liées à un objet avec un espace de nom réservé qui sera attribué dynamiquement en fonction de l'identifiant de l'objet. Nous sommes ainsi capables d'agir sur une variable numérique virtuellement liée à l'objet d'indice k.
Exemple d'algorithme :
Quand le personnage utilise l'objet k
Si la valeur de la variable questflag "objet_" + objet_id_k + "_count" est strictement inférieure à X alors
On incrémente de 1 la valeur de la variable questflag "objet_" + objet_id_k + "_count"
Sinon
On supprime la variable questflag "objet_" + objet_id_k + "_count" (un identifiant unique peut être réutilisé par un autre objet plus tard une fois l'objet détruit)
On supprime l'objet
Fin si
On téléporte le personnage
Fin
Avec cet algorithme, il n'y a rien à initialiser à l'obtention de l'objet. Tout se fait... tout seul. Il est redoutablement efficace et simple. Cependant, il ne pourra pas passer les obstacles suivants car l'objet ne serait alors plus lié au personnage.
Bonus : réponse possible aux autres obstacles
2eme solution : une technique plus énergivore à base de SQL
Il est possible d'accéder aux bases de données du jeu dans une quête. Comme je l'ai déjà énoncé, chaque objet dans le jeu est en faite représenté par une entrée dans la table item (base player) dans laquelle on trouvera les informations particulières à cet objet (tandis que les informations globales à tous les objets du même vnum se situeront dans item_proto). Où peut-on créer une variable, "un endroit", où mettre notre compteur qui serait lié à l'objet ?
Et bien la réponse paraît alors évidente : la table item, plus précisément dans l'entrée de l'objet étudié.
Nous avons plusieurs possibilités pour créer cette information : créer un nouveau champ ou utiliser un champ déjà existant.
La première a l'avantage d'être plus propre et claire. Cependant, elle affectera tous les objets du jeu et doit donc être initialisée intelligemment pour ne pas créer d'incohérence.
La seconde est plus du "bidouillage" et pourtant c'est peut être celle que je préférerai dans ce cas. La raison est la suivante : il est possible suite à des circonstances qui dépassent cette intervention (exemple d'une amélioration) qu'un objet perde son identifiant unique et devienne un "nouvel objet", avec un nouvel identifiant. Il sera alors recréé à l'identique (excepté le vnum qui sera incrémenté dans le cas de l'amélioration) grâce à une duplication des valeurs connues par le jeu de l'objet (bonus, pierres) présentes dans la table item. Si on utilise un champ déjà existant, il sera alors lui aussi recopié et donc sauvegardé dans le nouvel objet. Dans l'autre cas, la valeur du nouveau champ ne sera pas recopié.
Il nous faut donc choisir un champ déjà existant et non utilisé. Si le système s'adresse à un objet utilisable comme ici, je conseille d'utiliser une valeur de bonus (attrvalue) sans mettre d'attrtype. On aura alors aucun affichage graphique mais les données seront là. Dans le cas d'une arme ou d'une armure, on pensera à utiliser un des derniers socket.
Nous utiliserons pour la suite le champ attrvalue0. La valeur inscrite dans item_proto (s'appliquant à tous les objets du même vnum) sera 0 (initialisation). Ensuite, on procède de la même manière que dans le précédent algorithme.
Exemple d'algorithme :
Quand le personnage utilise l'objet k
On sélectionne avec une requête SQL la valeur de son attrvalue0 et on la stocke dans la variable count
Si la valeur de la variable count est strictement inférieure à X alors
On incrémente de 1 la valeur de son attrvalue0 à l'aide d'une requête SQL
Sinon
On supprime l'objet (le jeu se chargera de supprimer la ligne correspondante dans la table player)
Fin si
On téléporte le personnage
Fin
Le grand avantage de cette technique c'est qu'à priori elle triomphe de tous les obstacles que nous avons énumérés.
Cependant, je me dois de prévenir un éventuel utilisateur qu'il n'est pas conseillé d'utiliser des requêtes SQL dans les quêtes. Elles sont très énergivores, souvent peu efficaces (surtout dans une table aussi volumineuse que item) et pourront ralentir considérablement votre serveur.
Comment choisir ?
Cela dépend du besoin. Un anneau de téléportation à usage limité, je devine qu'il a sa place dans la boutique.
Est-il nécessaire de laisser aux joueurs le droit de l'échanger, de le jeter, de le mettre dans son entrepôt ou de le vendre ?
Si oui, alors il est obligatoire d'utiliser la deuxième technique présentée. Heureusement, il n'y aura qu'une utilisation pour une téléportation, avec à chaque deux requêtes. C'est donc une charge tout à fait acceptable pour un serveur avec un minimum de moyens.
Sinon, privilégiez la méthode avec les event flag qui est beaucoup plus efficace.
Merci de votre lecture (et pardonnez moi si j'ai fais des erreurs...).
-
1
- Que se passe-t-il si le personnage possède plusieurs fois l'objet ?
-
Oui, la dernière se fait également en SQL.
Cependant, il peut être utile de l'agrémenter avec un langage quelconque pour écrire le moins de lignes possibles.
En admettant que l'on souhaite donner les mêmes bonus à chaque classe, l'algorithme assez simple qui me vient en tête est le suivant :
définir dans un tableau les armes et armures de chaque classe (les bonus donnés seront les mêmes. Dans le cas de bonus différents, il faudra également définir les bonus pour chaque item pour chaque classe dans un tableau). Pour chaque personnage créé précédemment (tu peux mettre des bornes d'id par exemple) faire donner un bijoux au personnage avec les bonus définis préalablement (requête SQL) idem pour les autres bijoux sélectionner la classe du personnage (peut être pris au début si on utilise une requête SQL) donner l'arme qui correspond à la classe du personnage au personnage avec les bonus définis préalablement (requête SQL) idem pour l'armure fin pour
Pour les requêtes SQL à effectuer, tu peux te baser sur mon tutoriel (https://fr.metin2.dev/topic/12286-thread/).
-
Une requête SQL la aussi?
Oui, tout ce que tu as décris se fait avec quelques requêtes.
-
Tu peux toujours le faire manuellement via la base de données lorsque le serveur de jeu est coupé (pour éviter les bugs).
-
Pour les quêtes, modifiez directement l'encodage des fichiers concernés (.quest). Les miens sont encodés en ANSI (et non en UTF-8).
Pour les items / noms de mobs, dans "Design table" sur navicat, dans Type, j'utilise varbinary pour les noms.
-
Exact. J'y avais pas pensé
-
Niveau requis : Débutant
Temps estimé : 3 minutes
Bonjour,
RévélationVoici une fonction qui vous permettra de générer un mot de passe MySQL à la manière de PASSWORD().
<?php function mysqlPassword($raw){ return '*'.strtoupper(hash('sha1',pack('H*',hash('sha1', $raw)))); } ?>
Pour utiliser cette fonction, il vous suffit simplement d'appeler : mysqlPassword('votre mot de passe'); et elle vous retournera un mot de passe à la manière de la fonction PASSWORD() de MySQL.
Cordialement,
Hey hey
-
1
-
-
Si, on modifie l'encodage de votre champ MySQL (faisable sur Navicat) et de votre fichier dans votre éditeur de texte (sur Notepad++, voir encodage/convertir).
-
C'est un problème d'encodage.
-
C'est à dire que ton cms est obsolète et que ta fait un énorme retour dans le passé en le choisissant...
"mysql_connect(): The mysql extension is deprecated and will be removed in the future : use mysqli or PDO" est tout a fais normal sur wamp. Suffis juste de fermer skype, car Wamp a besoin du port 80 et comme j'ai pu voir que tu avais Skype qui lui utilise le port 80. Bonne soirée.
Qu'est-ce qu'il faut pas lire !
Cela vient simplement du fait que les fonctions du type mysql_ sont considérées comme archaïques. On te prévient d'ailleurs qu'elles risquent d'être supprimées dans une prochaine version de PHP. On te suggère de remplacer ces fonctions par mysqli_ ou PDO.
Tu peux choisir d'ignorer cet avertissement. Pour cela, tu peux directement modifier le niveau d'affichage des alertes dans ton fichier de configuration PHP. Sinon, tu peux faire ce qu'ils te proposent. La façon la plus simple est de passer en mysqli : tu as juste à rajouter un i derrière tous les mysql
-
En effet, le code
local test = number(1,9) while test > 5 do // Tant que "test" est supérieur à 5 faire local test = number(1,9) // "test" reprend une valeur aléatoire entre 1 et 9 end return test // retourne la valeur de test (supérieure à 5)
fonctionnera mais est faux d'un point de vue algorithmique. Le second local n'est en rien nécessaire.
Ce qu'il faut comprendre, c'est la portée de la variable test dans la boucle. Par exemple :
function test() while condition do local texte = "chaine" end return texte end
Ce code ne fonctionnera pas. La variable texte n'existe que dans la boucle et nul part ailleurs. Elle n'existe pas dans la fonction mère.
Par contre,
function test() local texte = "test" while condition do texte = "chaine" end return texte end
nous renverra "chaine" (et non "test"). La variable texte est créée dans la fonction et sa valeur est modifiée dans la boucle.
Il faut comprendre que si la variable est déclaré dans un élément parent, elle le sera dans un élément enfant.
Si la variable déclarée dans l'élément parent est modifiée dans l'élément enfant, alors elle sera modifiée également dans l'élément parent.
Attention : quand je parle de l'élément enfant, c'est uniquement une boucle ou une condition et JAMAIS un appel de fonction qui, si elle est déclarée dans un autre fichier, ne possède pas les variables de l'élément parent (d'où les arguments). Les arguments manipulés à l'intérieur de la fonction sont des copies des réels arguments situés dans l'élément "parent" (celui depuis lequel on a appelé la fonction) et donc ces derniers ne seront pas modifiés.
-
Lis bien ma dernière phrase. On ne cherche pas 33 mais 33% ^^
-
Pour protection des ténèbres, il faut que tu recherches le 33% dans ton game avec un éditeur hexa et que tu modifies ensuite sa valeur.
Petit indice : 100% est codé dans le game par FFFFFFFF.
-
C'est exact, autant pour moi. Je suis perverti par le C++
C'est bien le seul langage tellement haut niveau que les index des tableaux commencent à 1.
-
En effet, comme l'a précisé Prindo, les timer partiront au prochain logout.
Le meilleur moyen de faire une limite de temps pour un personnage est de rajouter un quest flag avec à l'intérieur un timestamp.
De plus, je pense que la quête plantera au compilage. Tu n'as pas le droit d'écrire :
if condition then //actions else condition2 then //actions end
C'est absolument interdit. Soit tu mets juste "else" (= dans tous les autres cas), soit tu mets "elseif".
On voit que tu es motivé. Pour améliorer ton code, je te propose plusieurs optiques :
- Essaie de donner à tes variables de vrais noms compréhensibles pour qu'on voit tout de suite ce à quoi elles font références. En effet, tu t'es régulièrement planté de variables (exemple à la fin). Tel quel, ton code ne fonctionnera surement pas.
- Rajouter un commentaire de temps en temps n'est pas une mauvaise chose (même si dans le cas d'une quête simple comme celle-ci ce n'est pas nécessaire).
- Essaie d'optimiser au maximum ton code. A la place de faire 50 000 if / else, essaie de manipuler les données avec plus de doigté. A la base, l'informatique est fait pour les flemmards. Ton but : faire le maximum de chose avec le moins de lignes possibles et avec la plus grande modularité. Evidemment, c'est pas toujours évident mais dans ton cas, cela aurait pu être amélioré. Voici un petit exemple :
- Code original (désolé pour l'indentation, c'est pas facile sur les forums en copié/collé)local b3 = number(1,2) if b3 == 1 then Say("La carte est bleue !") if pc.qetqf("bleu") == 1 then say("Vous avez remporté cette manche.") pc.give_item2(20003) pc.setqf("bleu_rouge", 2) elseif pc.qetqf("rouge") == 1 then say("Dommage, vous avez perdu cette manche.") pc.setqf("bleu_rouge", 2) end elseif b2 == 2 then if pc.qetqf("bleu") == 1 then say("Dommage, vous avez perdu cette manche.") pc.setqf("bleu_rouge", 2) elseif pc.qetqf("rouge") == 1 then say("Vous avez remporté cette manche.") pc.give_item2(20003) pc.setqf("bleu_rouge", 2) end end
- et la correction//Le choix de ton utilisateur devrait être mis dans un quest flag choix, ayant pour valeur 1 ou 2 (bleu ou rouge), ce qui réduira encore le nombre de lignes inutiles. On admettra ce fait pour la suite. local b3 = number(1,2) local couleurs_name = {"bleue", "rouge"} say("Le carte est "..couleurs_name[b3].." ! ") if b3 == pc.getqf("choix") then say("Vous avez remporté cette manche.") pc.give_item2(20003) else say("Dommage, vous avez perdu cette manche.") end pc.setqf("bleu_rouge", 2)
Je divise par 2 le nombre de lignes utilisées pour la même chose, et rend le code beaucoup plus modulable. Par exemple, si tu veux changer le nom d'une couleur, c'est très rapide et facile à faire. Si tu veux en rajouter une aussi...
Si tu as des questions, tu as mon Skype.
- Essaie de donner à tes variables de vrais noms compréhensibles pour qu'on voit tout de suite ce à quoi elles font références. En effet, tu t'es régulièrement planté de variables (exemple à la fin). Tel quel, ton code ne fonctionnera surement pas.
-
Après avoir essayé pas mal d'offres, le mieux est de toi même héberger ton site sur un serveur dédié différent de celui sur lequel tourne le jeu.
Tu pourras ainsi faire ce que tu veux avec (modifications apache, sécurités, mises à jour PHP). Après, c'est un peu plus cher...
Module Armurerie Metin2
dans Metin2
Posté(e)
Toute cette partie est déjà gérée par le projet précédent![;)](//funky-emu.net/applications/core/interface/js/spacer.png)