J'ai essayé de faire un poil plus simple que le dernier post, mais ça reste un petit pavé, je préviens !
Dans Ryzom, tous les calculs de gameplay sont calculés côté serveur ; le client ne fait pas grand chose d'autre que recevoir des informations du serveur et les afficher. Il faut aussi savoir que le temps pour le serveur (comme pour tous les serveurs de jeux vidéos) ne s'écoule pas de manière continue, mais par petits intervalles de temps (un peu comme une montre qui ne peut mesurer que des secondes minimum). On les appelent des "ticks", et la valeur pour Ryzom est de 100 millisecondes - autrement dit, le serveur est incapable de mesurer des évènements plus rapide que 100 millisecondes (soit une action est instantanée, soit elle dure au moins 100 millisecondes), et on a 10 ticks par seconde. Le choix dépend beaucoup du jeu (par exemple, les FPS ont souvent un tick serveur élevé, entre 30 et 60 ticks par seconde, car c'est des jeux très réactifs).
Maintenant qu'on sait ça, on peut se pencher sur les armes. Pour attendre entre 2 actions, Ryzom attend en fait un certain nombre (entier) de ticks. Du coup, quand une arme affiche 60 coups par minute, Ryzom va devoir traduire cette information en nombre de ticks entre deux coups. Pour ça, le calcul est très simple : 60 * 10 (60 secondes à 10 ticks chacune) / vitesse de l'arme. Ici, si on reprend l'exemple de notre dague, elle tape tous les (tout pile !) 10 ticks. Parfait !
Le problème, c'est que les divisions tombent rarement juste ! Si maintenant notre dague n'a que 59 coups par minute, on obtient une valeur de 600 / 59 ~= 10,17 ticks (j'ai arrondi à deux décimales pour ne pas trop complexifier mais ça ne change rien). Et vu que Ryzom ne compte que des nombres entiers de ticks, il applique un mécanisme simple : il tronque la valeur. Notre 10,17 devient 10 ticks, et notre arme à 59 coup/minute tape à la même vitesse que notre arme a 60 coup/minutes ... On a donc un problème à cause de ce tronquage, et des objets avec des vitesses différentes affichées ont en fait la même vitesse réelle !! C'est notre problème n°1 : la vitesse affichée n'est pas la bonne.
Évidemment, vu qu'un bug ne vient jamais seul, il y a aussi un autre problème : en réalité, les statistiques d'une arme (dégâts, vitesse, parade, etc) ne sont pas des nombres entiers comme affichés, mais des nombres à virgule (pour notre vitesse, en réalité elle vaut sûrement 59.43, et pas juste 59). Cependant, pour toutes les autres statistiques, on prend la valeur tronquée, et non pas la valeur réelle pour faire le calcul. Sauf pour la vitesse (pour une raison inconnue). Souvent, ça ne change pas grand chose ; entre 59.5 et 59, avec le tronquage on se ramène à la même valeur de ticks (10). Sauf dans des cas un peu particulier, juste autour d'un entier. Par exemple, si vous prenez une dague qui a une vitesse de 54.5 et une qui a une vitesse de 54.6, la première aura un temps d'attente de 11,01 ticks (soit 11 ticks), et la deuxième un temps d'attente de 10,99 ticks (soit 10 ticks). Du coup, vous avez deux dagues avec la même vitesse affichée, et qui ont une vitesse réelle différente. Et la seule manière de le savoir, c'est de passer par l'API (qui vous donne les valeurs précise pour un objet) - très clairement, ce n'est pas évident ... C'est notre problème n°2 : la vitesse de calcul est différente de la vitesse affichée.
Jamais deux sans trois, et cette fois-ci c'est un pur problème de logique au niveau du code qui gère les actions cycliques (celles qui se répètent, comme en particulier les attaques). Imaginez que vous avez un délai d'attente de 18 ticks (une pique full vitesse par exemple), et bien en pratique vous ne frapperez (et ferez des dégâts) que tous les 20 ticks. En effet, le gestionnaire de phrases sabrina (celui qui gère les actions cycliques), est un automate fini avec certains états (action démarrée, action en cours d'exécution, action en attente ...). Le changement d'état d'une action "en attente" (le délai n'est pas encore écoulé) à une action "en exécution" prend 2 ticks, vu la manière dont c'est codé. C'est notre problème n°3 : les attaques (ainsi que le forage) sont toutes ralenties de 2 ticks.
Enfin, un petit bug de précision & de tronquage fait que dans le cas d'une dague à 60 coups par minute, la vitesse calculée est de 9.99999 ticks, qui sera donc tronquée à 9 ticks, au lieu des 10 prévus. C'est notre problème n°4.
Vu que plusieurs vitesses en coup / minute permettent d'avoir la même vitesse réelle calculée, ça veut dire qu'il n'y a aucune différence entre une dague à 54.6 cpm et une à 60 cpm. Par contre, c'est bien plus facile de fabriquer une dague à 54.6 cpm, vu qu'il faut une statistique de vitesse bien plus faible : 81,83 contre 100 (ça veut dire qu'en suprême, vous n'aurez à priori pas besoin de mettre de mp qui donnent de la vitesse tant qu'aucune n'en enlève ... plutôt balèze hein ?). Pour trouver cette valeur c'est simple :
* On calcule l'attente en tick pour la valeur maximale de vitesse. Ici, 600 / 60 = 10 ticks.
* On prend la valeur en ticks juste supérieur (ici, 11), et on trouve la vitesse qui correspond : 600 / 11 = 54.55.
* On rentre cette valeur dans la formule de calcul de craft, qui est minimum + (maximum - minimum) * precraft = postcraft, donc ici pour la dague
30 + (60 - 30) * x = 54.55 <=> x = 0,8183, on multiplie ça par 100 pour avoir le precraft, ça nous fait 81,83
* Si on craft avec une vitesse > 81.9 (en prenant une petite marge de sécurité), on aura donc un délai d'attente en tick < 11 (donc tronqué à 10)
pre = (post - min) / (max-min)
Pour la valeur craft boost, c'est sensiblement similaire, on prend juste la valeur en ticks inférieure (17 pour une pique à 18, par exemple), on obtient le point de bascule [ne pas oublier de diviser par 1.2 pour avoir le precraft, c'est les 20% rubbarn] (par ex 93.15), avec une vitesse > 93.15 on aura donc un délai d'attente en tick < 17, donc tronqué à 16)
Pour trouver les informations pour toutes les armes (vitesse minimale, maximale, et donc temps d'attente en ticks), il suffit de regarder la config de l'EGS. Il faut savoir que les vitesses minimales / maximales ne sont pas des nombres entiers mais des nombres à virgule. Les valeurs precraft minimales à atteindre (craft normal, et craft boost) sont les suivantes : (il faut juste prendre une marge de sécurité de 0.1)
Arme - précraft - precraft boost
Dague - 81.82 - 83.33
Bâton / Épée 1M - 87.52 - 95.26
Massue / Hache 1M - 94.14 - 88.56
Lance - 93.05 - 89.92
Épée 2M - 90.48 - 92.1
Massue / Hache 2M - 91.33 - 91.29
Ici, on est clairement dans le cas de problèmes impactant le gameplay : deux armes identiques sur le client peuvent en fait avoir des dégâts par minute différents, toutes les armes sont plus lentes de 2 ticks que prévu (ce qui fait entre 8% et 14% de différence de dégâts par minute, c'est loin d'être négligeable), et enfin deux vitesses affichées différentes qui sont identiques en réalité, ce qui induit en erreur sur la véritable capacité de l'arme. Pour moi, tous ces bugs sont à régler, de la manière suivante :
Problème n°2 : Soit utiliser la valeur entière pour les calculs, soit afficher la valeur à virgule. Pour moi, c'est absurde d'afficher une valeur à virgule (on parle de coup/minutes), et il est mieux d'utiliser la valeur entière pour les calculs (comme dans pratiquement tous les calculs avec des objets, à part le facteur de protection, et ça a un peu de sens car une attaque pouvant monter facilement à 1000, la différence de dégâts entre deux valeurs distantes de 0.1% est au moins 1)
Problème n°3 : C'est un pur bug pour moi, il suffit juste de le régler et de permettre à une action de passer de l'état "en attente" à "en exécution" immédiatement.
Problème n°4 : Idem, un bug, régler l'arrondi.
Problème n°1 : Ici, c'est plus complexe à régler, car soit on modifie les valeurs de vitesse pour que "ça tombe bien" (indice : c'est pas possible si on veut garder la diversité d'armes qu'il y a sur Ryzom), soit on compte des délais d'attente non pas en valeur entière (10 ticks), mais en valeur à virgule (10.2 ticks). Ça veut dire que vos actions d'attaque ressembleraient à ça :
* t=0, attaque n°0
* t=10, attaque n°1
* t=20, attaque n°2
* t=30, attaque n°3
* t=40, attaque n°4
* t=51, attaque n°5
* t=61, attaque n°6
* t=71, attaque n°7
* t=81, attaque n°8
* t=91, attaque n°9
* t=102, attaque n°10
On aurait donc 5 attaques en 51 ticks (notez qu'au début on a une petite différence car la première attaque est instantanée).
En fait, il se trouve que ce n'est pas très difficile à changer, et faisable uniquement pour le sous-système qui s'occupe des actions cycliques (on ne touche pas à l'immense majorité du code des ticks, ce qui évite les bugs partout).
Il se trouve que tout ceci a été réglé dans RyzomCore, de la manière que j'ai indiqué comme préférentielle (c'est normal, c'est moi qui ai fait les fix). Il suffirait donc simplement à Winchgate d'intégrer les bugfix à leur code (et, si ma manière de faire ne convient pas, changer à leur goût, ce qui est relativement facile à faire vu que j'ai identifié toutes les parties du code qui posent problème et expliqué les mécanismes internes du sabrina manager). Ceci ayant été fait il y a 3 mois, j'imagine que ce n'est pas une de leur priorité, ce qui est dommage à mon goût (et si jamais ils le font, pensez aussi à merge le fix pour le bug des monstres buggués qui n'aggro plus, cf l'issue RC, ça serait super cool parce que j'en vois partout maintenant :D). Je sais que c'est pas forcément évident de merge du code, mais là le fonctionnement étant identique entre le serveur officiel et RyzomCore, le code derrière est à priori le même ... donc ça devrait aller :)
Bisous à tous, si quelqu'un a la motivation de traduire ça en anglais et/ou allemand ça serait sympa, je le rajouterai au post (j'avoue que je n'ai pas la motivation de le faire pour l'anglais, et l'incapacité complète de le faire pour l'allemand)
Rappels sur le serveur Ryzom
Dans Ryzom, tous les calculs de gameplay sont calculés côté serveur ; le client ne fait pas grand chose d'autre que recevoir des informations du serveur et les afficher. Il faut aussi savoir que le temps pour le serveur (comme pour tous les serveurs de jeux vidéos) ne s'écoule pas de manière continue, mais par petits intervalles de temps (un peu comme une montre qui ne peut mesurer que des secondes minimum). On les appelent des "ticks", et la valeur pour Ryzom est de 100 millisecondes - autrement dit, le serveur est incapable de mesurer des évènements plus rapide que 100 millisecondes (soit une action est instantanée, soit elle dure au moins 100 millisecondes), et on a 10 ticks par seconde. Le choix dépend beaucoup du jeu (par exemple, les FPS ont souvent un tick serveur élevé, entre 30 et 60 ticks par seconde, car c'est des jeux très réactifs).
Calcul de la vitesse
Maintenant qu'on sait ça, on peut se pencher sur les armes. Pour attendre entre 2 actions, Ryzom attend en fait un certain nombre (entier) de ticks. Du coup, quand une arme affiche 60 coups par minute, Ryzom va devoir traduire cette information en nombre de ticks entre deux coups. Pour ça, le calcul est très simple : 60 * 10 (60 secondes à 10 ticks chacune) / vitesse de l'arme. Ici, si on reprend l'exemple de notre dague, elle tape tous les (tout pile !) 10 ticks. Parfait !
Le problème, c'est que les divisions tombent rarement juste ! Si maintenant notre dague n'a que 59 coups par minute, on obtient une valeur de 600 / 59 ~= 10,17 ticks (j'ai arrondi à deux décimales pour ne pas trop complexifier mais ça ne change rien). Et vu que Ryzom ne compte que des nombres entiers de ticks, il applique un mécanisme simple : il tronque la valeur. Notre 10,17 devient 10 ticks, et notre arme à 59 coup/minute tape à la même vitesse que notre arme a 60 coup/minutes ... On a donc un problème à cause de ce tronquage, et des objets avec des vitesses différentes affichées ont en fait la même vitesse réelle !! C'est notre problème n°1 : la vitesse affichée n'est pas la bonne.
Évidemment, vu qu'un bug ne vient jamais seul, il y a aussi un autre problème : en réalité, les statistiques d'une arme (dégâts, vitesse, parade, etc) ne sont pas des nombres entiers comme affichés, mais des nombres à virgule (pour notre vitesse, en réalité elle vaut sûrement 59.43, et pas juste 59). Cependant, pour toutes les autres statistiques, on prend la valeur tronquée, et non pas la valeur réelle pour faire le calcul. Sauf pour la vitesse (pour une raison inconnue). Souvent, ça ne change pas grand chose ; entre 59.5 et 59, avec le tronquage on se ramène à la même valeur de ticks (10). Sauf dans des cas un peu particulier, juste autour d'un entier. Par exemple, si vous prenez une dague qui a une vitesse de 54.5 et une qui a une vitesse de 54.6, la première aura un temps d'attente de 11,01 ticks (soit 11 ticks), et la deuxième un temps d'attente de 10,99 ticks (soit 10 ticks). Du coup, vous avez deux dagues avec la même vitesse affichée, et qui ont une vitesse réelle différente. Et la seule manière de le savoir, c'est de passer par l'API (qui vous donne les valeurs précise pour un objet) - très clairement, ce n'est pas évident ... C'est notre problème n°2 : la vitesse de calcul est différente de la vitesse affichée.
Jamais deux sans trois, et cette fois-ci c'est un pur problème de logique au niveau du code qui gère les actions cycliques (celles qui se répètent, comme en particulier les attaques). Imaginez que vous avez un délai d'attente de 18 ticks (une pique full vitesse par exemple), et bien en pratique vous ne frapperez (et ferez des dégâts) que tous les 20 ticks. En effet, le gestionnaire de phrases sabrina (celui qui gère les actions cycliques), est un automate fini avec certains états (action démarrée, action en cours d'exécution, action en attente ...). Le changement d'état d'une action "en attente" (le délai n'est pas encore écoulé) à une action "en exécution" prend 2 ticks, vu la manière dont c'est codé. C'est notre problème n°3 : les attaques (ainsi que le forage) sont toutes ralenties de 2 ticks.
Enfin, un petit bug de précision & de tronquage fait que dans le cas d'une dague à 60 coups par minute, la vitesse calculée est de 9.99999 ticks, qui sera donc tronquée à 9 ticks, au lieu des 10 prévus. C'est notre problème n°4.
Application au craft
Vu que plusieurs vitesses en coup / minute permettent d'avoir la même vitesse réelle calculée, ça veut dire qu'il n'y a aucune différence entre une dague à 54.6 cpm et une à 60 cpm. Par contre, c'est bien plus facile de fabriquer une dague à 54.6 cpm, vu qu'il faut une statistique de vitesse bien plus faible : 81,83 contre 100 (ça veut dire qu'en suprême, vous n'aurez à priori pas besoin de mettre de mp qui donnent de la vitesse tant qu'aucune n'en enlève ... plutôt balèze hein ?). Pour trouver cette valeur c'est simple :
* On calcule l'attente en tick pour la valeur maximale de vitesse. Ici, 600 / 60 = 10 ticks.
* On prend la valeur en ticks juste supérieur (ici, 11), et on trouve la vitesse qui correspond : 600 / 11 = 54.55.
* On rentre cette valeur dans la formule de calcul de craft, qui est minimum + (maximum - minimum) * precraft = postcraft, donc ici pour la dague
30 + (60 - 30) * x = 54.55 <=> x = 0,8183, on multiplie ça par 100 pour avoir le precraft, ça nous fait 81,83
* Si on craft avec une vitesse > 81.9 (en prenant une petite marge de sécurité), on aura donc un délai d'attente en tick < 11 (donc tronqué à 10)
pre = (post - min) / (max-min)
Pour la valeur craft boost, c'est sensiblement similaire, on prend juste la valeur en ticks inférieure (17 pour une pique à 18, par exemple), on obtient le point de bascule [ne pas oublier de diviser par 1.2 pour avoir le precraft, c'est les 20% rubbarn] (par ex 93.15), avec une vitesse > 93.15 on aura donc un délai d'attente en tick < 17, donc tronqué à 16)
Pour trouver les informations pour toutes les armes (vitesse minimale, maximale, et donc temps d'attente en ticks), il suffit de regarder la config de l'EGS. Il faut savoir que les vitesses minimales / maximales ne sont pas des nombres entiers mais des nombres à virgule. Les valeurs precraft minimales à atteindre (craft normal, et craft boost) sont les suivantes : (il faut juste prendre une marge de sécurité de 0.1)
Arme - précraft - precraft boost
Dague - 81.82 - 83.33
Bâton / Épée 1M - 87.52 - 95.26
Massue / Hache 1M - 94.14 - 88.56
Lance - 93.05 - 89.92
Épée 2M - 90.48 - 92.1
Massue / Hache 2M - 91.33 - 91.29
Régler les problèmes ?
Ici, on est clairement dans le cas de problèmes impactant le gameplay : deux armes identiques sur le client peuvent en fait avoir des dégâts par minute différents, toutes les armes sont plus lentes de 2 ticks que prévu (ce qui fait entre 8% et 14% de différence de dégâts par minute, c'est loin d'être négligeable), et enfin deux vitesses affichées différentes qui sont identiques en réalité, ce qui induit en erreur sur la véritable capacité de l'arme. Pour moi, tous ces bugs sont à régler, de la manière suivante :
Problème n°2 : Soit utiliser la valeur entière pour les calculs, soit afficher la valeur à virgule. Pour moi, c'est absurde d'afficher une valeur à virgule (on parle de coup/minutes), et il est mieux d'utiliser la valeur entière pour les calculs (comme dans pratiquement tous les calculs avec des objets, à part le facteur de protection, et ça a un peu de sens car une attaque pouvant monter facilement à 1000, la différence de dégâts entre deux valeurs distantes de 0.1% est au moins 1)
Problème n°3 : C'est un pur bug pour moi, il suffit juste de le régler et de permettre à une action de passer de l'état "en attente" à "en exécution" immédiatement.
Problème n°4 : Idem, un bug, régler l'arrondi.
Problème n°1 : Ici, c'est plus complexe à régler, car soit on modifie les valeurs de vitesse pour que "ça tombe bien" (indice : c'est pas possible si on veut garder la diversité d'armes qu'il y a sur Ryzom), soit on compte des délais d'attente non pas en valeur entière (10 ticks), mais en valeur à virgule (10.2 ticks). Ça veut dire que vos actions d'attaque ressembleraient à ça :
* t=0, attaque n°0
* t=10, attaque n°1
* t=20, attaque n°2
* t=30, attaque n°3
* t=40, attaque n°4
* t=51, attaque n°5
* t=61, attaque n°6
* t=71, attaque n°7
* t=81, attaque n°8
* t=91, attaque n°9
* t=102, attaque n°10
On aurait donc 5 attaques en 51 ticks (notez qu'au début on a une petite différence car la première attaque est instantanée).
En fait, il se trouve que ce n'est pas très difficile à changer, et faisable uniquement pour le sous-système qui s'occupe des actions cycliques (on ne touche pas à l'immense majorité du code des ticks, ce qui évite les bugs partout).
Il se trouve que tout ceci a été réglé dans RyzomCore, de la manière que j'ai indiqué comme préférentielle (c'est normal, c'est moi qui ai fait les fix). Il suffirait donc simplement à Winchgate d'intégrer les bugfix à leur code (et, si ma manière de faire ne convient pas, changer à leur goût, ce qui est relativement facile à faire vu que j'ai identifié toutes les parties du code qui posent problème et expliqué les mécanismes internes du sabrina manager). Ceci ayant été fait il y a 3 mois, j'imagine que ce n'est pas une de leur priorité, ce qui est dommage à mon goût (et si jamais ils le font, pensez aussi à merge le fix pour le bug des monstres buggués qui n'aggro plus, cf l'issue RC, ça serait super cool parce que j'en vois partout maintenant :D). Je sais que c'est pas forcément évident de merge du code, mais là le fonctionnement étant identique entre le serveur officiel et RyzomCore, le code derrière est à priori le même ... donc ça devrait aller :)
Bisous à tous, si quelqu'un a la motivation de traduire ça en anglais et/ou allemand ça serait sympa, je le rajouterai au post (j'avoue que je n'ai pas la motivation de le faire pour l'anglais, et l'incapacité complète de le faire pour l'allemand)
---
