Tracer les DLLs - Fonction de calcul des dégats physiques

M

Myrdinn

Invité
Tracer les Dlls -- Post 3 LA routine de calcul des dégats des bases.
Les posts précédents donnant les bases permettant une meilleure compréhension sont ICI et LA


Je dois commencer par un exemple détaillé de ce que l'on peut obtenir. Dans le prochain post nous ferrons le trace de cette partie, pour eviter de partir de rien, je vais décrire la fonction en détail même si pour l'instant vous n'avez pas forcement les moyens de savoir d'ou je tire mes informations (Vous le verrez par la suite) Bref la fonction de calcul des dégats physique.

Pour commencer une explication du format du post.
Le code est représenté en citation
La première colonne représente l'adresse du code dans la dll(Offset)
Le deuxième l'instruction assembleur en hexa
La troisième la même instruction en OpCode

Code:
Section 1 Initialisation de la fonction
0007DC38   90               NOP
0007DC39   90               NOP
0007DC3A   90               NOP
0007DC3B   90               NOP
0007DC3C   90               NOP
0007DC3D   90               NOP
0007DC3E   90               NOP
0007DC3F   90               NOP
0007DC40   83EC 08          SUB ESP,8
0007DC43   53               PUSH EBX
0007DC44   55               PUSH EBP
0007DC45   56               PUSH ESI
0007DC46   57               PUSH EDI
LA fonction commence en 0007DC40 (par commodité j'oublierais les OOO par la suite). C'est le code de la 1.09B pour la 1.09D le code commence en 0007E140
C'est le moment de voir une nouvelle instruction NOP
NOP=No Operation. Demande au processeur de ne rien faire :).
En réalité c'est l'alias d'une fonction qui ne fait rien. A quoi ca sert? A faire du remplissage dans les Dlls. Si vous voulez faire un mod ou tout les degats physiques sont annulés vous n'avez qu'à remplacer tout ce que l'on va voir dans ce post par des NOP.Tout ca pour vous dire que blizzard entoure fréquemment ces fonctions par des NOPs pour les délimiter, c'est d'ailleurs très gentil de leur part.
Venons en à la fonction. On voit une modification du pointeur de la pile on lui retire 8 (Donc on laisse 2Dwords supplémentaires) et on pousse 4 registres !!! Il faut ce souvenir que cette fonction comme toutes les autres est appelé par le programme principal qui utilise également les registres. Ce qui se passe ici c'est une sauvegarde de ces registres sur la pile pour récupération à la fin de cette fonction. D'ailleurs si vous regardez la fin de la fonction vous avez exactement le contraire et les NOPs après qui servent de remplissage.
Au passage vous remarquerez que les regsitres en X ne sont jamais sauvegardés. Si leur contenu est important il faut toujours le sauvegarder autre part. C'est ce que fait DiabloII on aura l'occasion de le voir.

Code:
0007DC47   8BF1             MOV ESI,ECX
0007DC49   6A 00            PUSH 0
0007DC4B   8BFA             MOV EDI,EDX
0007DC4D   56               PUSH ESI
0007DC4E   E8 F5710400      CALL 000C4E48(D2Common.Dll Fonction exportée 10434)
La on commence vraiment la fonction.
Il faut que je vous parle du pipelining des processeurs. Les processeurs modernes ne traitent pas les instructions assembleur ligne par ligne, mais plusieurs instructions en même temps en parrallèle (dans des "pipelines") si celle ci ne dépendent pas du résultat de la précedente.
Par exemple
MOV EAX,64
ADD EBX,EAX
ne bénéficie pas du pipeline car le résultat dans EBX dépend de l'instruction précédente qui charge 100 dans EAX.
Bref pour des questions de gain de rapidité vous verrez souvent des mélanges de lignes pour des raison d'optimisation. C'est le cas ici (Pour ESI), vous avez 2 Morceaux de code distinct.

MOV ESI,ECX
MOV EDI,EDX
La fonction récupère les paramètres passés dans ECX et EDX.
Désormais
ESI=Pointeur sur l'objet Attaquant
EDI=Flag combat
Dans le quatrième post je vous expliquerais comment savoir que ce sont ces paramètres qui sont passés. Ne vous inquiétez pas je vous donne beaucoup d'info mais vous verrez quand ce sera possible d'ou elles viennent

et
PUSH 0
PUSH ESI
CALL D2Common.dll 10434
Une explication des appels de fonctions Exportées. Lorsque l'on appelle une fonction exportée on passe les paramètres sur la pile (Les PUSH). Sinon pour les appel internes à la dll les paramètres sont passés dans les registres (C'est le cas juste au dessus, les 2 MOV) Ensuite on appelle la fonction avec un CALL (C'est notre outil qui vous donnera le numéro de la fonction appelée). Le résultat sera toujours renvoyé dans EAX.
Que fait cette fonction?
Cette fonction retourne dans EAX le pointeur sur l'Arme dans la main Paramètre 1 de l'unité (Param2) ou 0 si l'unité est à main nue.
Ici
Paramètres 1. 0= principal (1=Secondaire)
Paramètre 2. Pointeur sur l'UNIT concernée (Ici l'attaquant).
Bref EAX=Pointeur sur l'arme Active[/red]

On pourrait tracer cette fonction, mais j'ai fait le choix de ne jamais sortir de la fonction principale. Sinon on ne reveindrait dans le sujet de ce post que dans une dizaine de millier de lignes de codes :D. Donc on se contetera ici et par la suite de regarder le résultat dans EAX

CONCLUSION de la section 1
Cette partie est extremement commune, on verra l'équivalent dans la plupart des fonctions. Ce qu'il faut retenir pour la suite c'est
ESI=Pointeur sur l'unit Attaquant
EDI= Flag. Je n'en dit pas plus exprès pour vous donnez la démarche a suivre.
EAX=Pointeur sur l'objet Arme.
 
H

hohorga

Invité
Trés intéressant !

A noter que les nop servent aussi à faire du code qui s'auto-modifie et donc s'auto-optimise : ça permet de faire rentrer des instructions plus longues et des instrructions supplémentaires. Bon c'est un bien grand mot s'auto-optimise...

M'enfin on faisait ça sur Atari ST car je crois que sur PC l'optimisation c'est pas trop le cheval de bataille des éditeurs :o

En tout cas félicitation, ça me donne envie d'aller taper dans les dll de didi :)

Merci.
 
W

wakestorm

Invité
Ouch, gros :gratz: a toi :D

Je me mets a lire tout de suite, mais vu l'heure, je sais pas si je vais tout comprendre direct, mais enfin j'ai demain, après demain et deux semaines de vacances pour comprendre :lol:

edit : c'est dingue, c'est plus facile que les MPQ, le seul hik, c'est l'hexadécimal, si tu pouvais faire un post un jour, ce serait très sympa ;)
 
M

Myrdinn

Invité
Avant de continuer une petite explication sur mes méthodes de travail. jusqu'ici quelque soit les données toutes ces instructions sont éxécutées. Dans le morceau de code que nous allons voir la fonction va faire des tests et faire des choix en conséquence. Je décompose les fonctions en plusieurs parties 1,2,3... Ensuite quand il existe des parties facultatives, je donne des lettres aux sous parties distinctes donc Ici 2A,2B,2C ... voir même 2AA,2AB si j'ai encore des subdivision. Rien ne vous oblige à faire comme moi. Cela implique qu'avant de lire le contenu en détails vous regardiez les différents Jump et que vous fassiez une cartographie de la fonction.
Bref passons à la partie 2.

Code:
PARTIE 2. Tests préliminaires
0007DC53   85FF             TEST EDI,EDI
0007DC55   894424 10        MOV DWORD PTR SS:[ESP+10],EAX
0007DC59   74 7D            JE SHORT 0007DCD8
0007DC5B   85C0             TEST EAX,EAX
0007DC5D   74 4A            JE SHORT 0007DCA9
0007DC5F   8B86 84000000    MOV EAX,DWORD PTR DS:[ESI+84]
0007DC65   50               PUSH EAX
0007DC66   56               PUSH ESI
0007DC67   E8 D6710400      CALL 000C4E42
0007DC6C   83F8 02          CMP EAX,2
0007DC6F   75 1C            JNZ SHORT 0007DC8D
C'est la que ce fait le "flow control" ou si vous préferez les choix et les différents branchements qui en résulte.
Bon on commence par un peu de pipeling. MOV DWORD PTR SS:[ESP+10],EAX fait partie de la fonction 1 mais le pipeline fait que l'on test EDI auparavant.
MOV DWORD PTR SS:[ESP+10],EAX Une des forme de l'instruction MOV mais toujours MOV A,B equivalent à copier B dans A. Ici on copie EAX(Le pointeur de l'arme)sur la pile en position +10(En hexa +16 en décimaldonc le 5eme DWORD de la pile) sous forme de DWORD (32 Bits) pour le sauvegarder.
Vous verrez ca en image dans le prochain post patience.

Premier test et choix
TEST EDI,EDI
MOV ...(Pipeline dont je viens de vous parler)
JE SHORT 0007DCD8
Je ne rentrerais pas dans les détails des tests cette fois ci car nous avons assez de choses à voir, nous le ferrons avec le trace car on voit les flags register changé en direct.
Test A,A
JE Address
Correspond au test si A=0 alors passé directement à address
N.B. Le SHORT du jump correspond à un saut dans le même segment mémoire, C'est le programme que nous utiliserons qui calcule l'adresse (d'ailleurs vous voyez je donne les adresses, peut importe si c'est un jump proche ou lointain pour nous)

Dans notre cas on test si EDI vaut0?. Si EDI=0 alors on passe à la section 2D(0007DCD8). Rappelez vous EDI contient un flag de combat, nous verrons plus tard à quoi il sert (dans la section 2D justement)

Deuxième Choix
TEST EAX,EAX
JE SHORT 0007DCA9
Même principe. EAX=Pointeur sur arme. Bref si l'attaquant n'a pas d'arme alors Jump Section 2C(0007DCA9)

Troisième et quatrième choix
0007DC5F......8B86 84000000...... MOV EAX,DWORD PTR DS:[ESI+84]
0007DC65......50..............................PUSH EAX
0007DC66......56..............................PUSH ESI
0007DC67......E8 D6710400............CALL 000C4E42(D2COMMON.dll Fonction 10291)
On place dans EAX le doubleWord situé en position +84 par rapport à ESI(Position +84 de l'objet attaquant=Pointeur sur Equipement). Vous connaissez cette forme de MOV Maintenant.
Ensuite la forme habituelle d'appel d'un fonction à 2 paramètres
EAX= Pointeur sur l'unité équipement.
ESI= Pointeur sur l'unité Attaquant.
La fonction 10291 retourne dans EAX le nombre de main avec laquelle l'arme est utilisée. 1= Une main 2=a 2 mains.
Le test qui suit permet de départager les choix 3 et 4
0007DC6C......83F8 02.................. CMP EAX,2
0007DC6F......75 1C........................JNZ SHORT 0007DC8D
On compare le resultat EAX avec 2
JNZ signifiant Jump if Not Zero. Bref on compare EAX(Le nombre de mains utilisées pour porter l'arme) avec 2, s'il y a une différence=Not Zero (Donc si on porte l'arme à une main) on passe à la section 2B
Sinon on continue
La suite est donc la section 2A dans ma nomenclature elle concerne les attaquants ayant une arme à 2 mains.
 
M

Myrdinn

Invité
Code:
SECTION 2A - Arme à 2 mains
0007DC71   6A 17            PUSH 17
0007DC73   56               PUSH ESI
0007DC74   E8 13670400      CALL 000C438C
0007DC79   8BD8             MOV EBX,EAX
0007DC7B   6A 18            PUSH 18
0007DC7D   56               PUSH ESI
0007DC7E   E8 09670400      CALL 000C438C
0007DC83   8BE8             MOV EBP,EAX
0007DC85   C1E3 08          SHL EBX,8
0007DC88   C1E5 08          SHL EBP,8
0007DC8B   EB 53            JMP SHORT 0007DCE0
On commence par un appel distant à la fonction 10519 avec 2 paramètres. 17 et le pointeur de l'attaquant.
C'est la fonction la plus important de D2COmmon.dll. Elle permet de lire la propriété d'un objet et de la retourner dans EAX. Vous devez absolument la retenir, car ce sera souvent la base de vos recherche de nouvelle fonction.
Pour comprendre cette donction vous avez besoin de ce fichier extrait des MPQ.
JE vous le donne au format excel car j'ai fait des traitements dessus pour des recherches qui ne concernent pas ce post. C'est evidemment un fichier txt que vous pouvez extraire vous même des MPQs. La fonction 10519 traite le fichier .bin généré à partir de ce fichier.
Bon seules les 2 premières colonne nous interresse. En premier on trouve la propriété. En deuxième le numéro d'ID en décimal (La fonction elle le traite en hexa = deuxième paramètres (ordre inverse des push car il s'agit de la pile))
Bref on lit la propriété 17 de l'objet attaquant = STAT_SECONDARY_MINDAMAGE. Bref les dégats secondaires mini de l'objet joueur. (Secondaires car les principaux concernent les dégats à 1 main). Un petit point la dessus. Toutes les unités utilisent ce fichier, que vous soyez un monstre, un paladin, un mercenaire, une epee, une armure... vous utilisez toujours cette liste.
Quand votre personnage equipe ou déséquipe un objet, les propriétés de cet objet (défini par ce fichier) sont ajoutéés/retirées de votre unité personnage. C'est
pourquoi les % des propriétés comme deadly strike, crushing blow s'additionnent, car les seules propriétés testés par le jeu pendant les combats sont celles des unités joueurs et monstres et jamais de leur équipement qui une fois équipé n'est plus pris en compte par le jeu...
Nous verrons la partie qui gère ces propriétés une autre fois peut être (ou vous la verrez tous seul quand vous saurez faire les trace par vous même).
Ici la formule pour les dégats mini sont
Dégats mini=(Dégats mini de base de l'arme(x1,5 si l'arme est ethérée)x (1+%ED de l'arme/100) + Dégats mini (Provenant de tout l'équipement arme,charme,armure ...)
C'est déjà une exception à la règle du dessus car les %ED directement sur l'arme ne sont pas ajoutés a votre objet personnage mais sont ajouté au dégats de base de l'arme puis ignorés par la suite.

Revenons a cette partie.
PUSH 17
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBX,EAX
Donc la fonction récupère les dégats mini (Propriété 17h=23 en décimal) de l'unité attauqant dans EAX.
Ensuite le jeu copie le résultat dans EBX

PUSH 18
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBP,EAX
La fonction récupère les dégats maxi (STAT_SECONDARY_MAXDAMAGE) de l'unité attaquant dans EAX puis copie le résultat dans EBP

SHL EBX,8
SHL EBP,8

La fonction SHL A,x pour ShiftLeft décale les bits de A de x bits vers la gauche Exemple SHL EAX,2 avec EAX= 00001010 donne comme résultat EAX=00101000.
chaque déplacement de 1 vers la gauche équivaut à une multiplication par 2.

Bref ici on multiplie les dégats mini et max par 256???
JE vous en ai déjà parlé c'est l'extra précision. LEs données dans diabloII ont le format d'un DWORD (32 bits = 4 bytes) Les 3 premiers BYTES sont destiné aux humains, c'est uniquement ceux la que le jeu affiche. LE dernier BYTES correspond à l'extra précision, on peut comparer ca aux chiffres derrière la virgule.
Un exmple admettons que EBX contiennent les dégats mini, si j'ecrit EBX en hexa voyons l'exemple suivant
EBX = 00 00 10 00. pour le jeu vous faites 16*256 dégats mini. Votre fenettre de personnage n'affichera que 00 00 10 soit 16 points de dégats mini le 00 qui suit servant d'extra précision pour les calculs fin du jeu. C'est de cette façon que le jeu vous affiche des 4,5 point de mana pour jeter un sort alors que le jeu ne gère que des nombre entier. 4,5 point de mana s'écrit dans ce système 00 00 04 80

il reste une instructions
JMP SHORT 0007DCE0
Saut à la section 3 la section 2A est terminée.

Code:
Section 2B - Arme à une main
0007DC8D   6A 15            PUSH 15
0007DC8F   56               PUSH ESI
0007DC90   E8 F7660400      CALL 000C438C
0007DC95   8BD8             MOV EBX,EAX
0007DC97   6A 16            PUSH 16
0007DC99   56               PUSH ESI
0007DC9A   E8 ED660400      CALL 000C438C
0007DC9F   8BE8             MOV EBP,EAX
0007DCA1   C1E3 08          SHL EBX,8
0007DCA4   C1E5 08          SHL EBP,8
0007DCA7   EB 37            JMP SHORT 0007DCE0
C'est presque la même.

PUSH 15
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBX,EAX
Récupère la propriété 15(21 en décimal) de l'unité Attaquant et le place dans EBX
EBX = STAT_MINDAMAGE. Ca se passe d'explication :)
Dégats mini=(Dégats mini de base de l'arme(x1,5 si l'arme est ethérée)x (1+%ED de l'arme/100) + Dégats mini (Provenant de tout l'équipement arme,charme,armure ...)

PUSH 16
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBP,EAX
Récupère les dégats max dans EBP
avec comme toujours Dégats Max=(Dégats max de base de l'arme(x1,5 si l'arme est ethérée)x(1+%ED de l'arme/100) + Dégats maxi (Provenant de tout l'équipement arme,charme,armure ...)

SHL EBX,8
SHL EBP,8
JMP SHORT 0007DCE0 (Section 3)
On multiplie par 256 (Pour l'extra précision) puis on passe directement à la section 3

Code:
Section 2C - Sans Arme
0007DCA9   6A 15            PUSH 15
0007DCAB   56               PUSH ESI
0007DCAC   E8 DB660400      CALL 000C438C
0007DCB1   8BD8             MOV EBX,EAX
0007DCB3   85DB             TEST EBX,EBX
0007DCB5   7F 05            JG SHORT 0007DCBC
0007DCB7   BB 01000000      MOV EBX,1
0007DCBC   6A 16            PUSH 16
0007DCBE   56               PUSH ESI
0007DCBF   E8 C8660400      CALL 000C438C
0007DCC4   8BE8             MOV EBP,EAX
0007DCC6   83FD 01          CMP EBP,1
0007DCC9   7F 05            JG SHORT 0007DCD0
0007DCCB   BD 02000000      MOV EBP,2
0007DCD0   C1E3 08          SHL EBX,8
0007DCD3   C1E5 08          SHL EBP,8
0007DCD6   EB 08            JMP SHORT 0007DCE0

PUSH 15
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBX,EAX
Idem EBX=Dégats mini donc réduit à sa plus faible expression (puisque dégat de base de l'arme= 0)= + degats mini de tout l'equipement (charme armure ...)

TEST EBX,EBX
JG SHORT 0007DCBC
MOV EBX,1
On test si EBX=0 (Donc si dégat mini =0)
On saute MOV EBX,1 si EBX>0 sinon EBX=1.
Bref si dégat mini n'est pas supérieur à 0 alors dégat mini = 1

PUSH 16
PUSH ESI
CALL D2COMMON.DLL 10519
MOV EBP,EAX
Idem EBP=Dégat MAxi réduit au minimum (+ Degats maxi sur l'équipement car dégats de l'arme=0)

CMP EBP,1
JG SHORT 0007DCD0
MOV EBP,2
On compare les dégat max avec 1 Si ils sont supérieur à 1 on passe à la partie suivante autrement MOV EBP,2 Degats max = 2

SHL EBX,8
SHL EBP,8
JMP SHORT 0007DCE0 (Section 3)
On multiplie par 256 (Pour l'extra précision) puis on passe directement à la section 3. Comme d'habitude


Code:
Section 2D - Ne pas prendre ne compte l'arme
0007DCD8   8B6C24 20        MOV EBP,DWORD PTR SS:[ESP+20]
0007DCDC   8B5C24 1C        MOV EBX,DWORD PTR SS:[ESP+1C]
Bon vous vous rappelez au début on test un Flag dans EDI. Si le flag=0 on arrive a cette section. Bref on ignore l'arme de l'attaquant. Cette routine de calcul sert à tous les dégats physique y compris ceux d'épine et de dame de FER. Dans ce cas il ne faut pas que les dégats de l'arme soit pris en compte. C'est à cela que sert ce flag.
Dans ce cas EBP=Degats maxi passés par l'aptitude qui a générée les dégats(Iron maiden ...)
EBX=Degats mini passés par l'aptitude qui a générée les dégats(Iron maiden ...)
Vous verrez par la suite et grace aux traces d'ou viennent ces informations.

Nous avons fini avec la section 2
Dans cette section on calcule les degats mini et max suivant l'arme utilisée.
Il faut retenir pour la suite
EBX=Degats mini
EBP=Degats MAxi les 2 avec l'extra précision de 1 bytes.
 
M

Myrdinn

Invité
Code:
Section 3
0007DCE0   83FB 01          CMP EBX,1
0007DCE3   7D 05            JGE SHORT 0007DCEA
0007DCE5   BB 00010000      MOV EBX,100
0007DCEA   3BEB             CMP EBP,EBX
0007DCEC   7F 06            JG SHORT 0007DCF4
0007DCEE   8DAB 00010000    LEA EBP,DWORD PTR DS:[EBX+100]
0007DCF4   6A 19            PUSH 19
0007DCF6   56               PUSH ESI
0007DCF7   E8 90660400      CALL 000C438C
0007DCFC   8B7C24 24        MOV EDI,DWORD PTR SS:[ESP+24]
0007DD00   6A 12            PUSH 12
0007DD02   56               PUSH ESI
0007DD03   03F8             ADD EDI,EAX
0007DD05   E8 82660400      CALL 000C438C
0007DD0A   6A 11            PUSH 11
0007DD0C   56               PUSH ESI
0007DD0D   894424 2C        MOV DWORD PTR SS:[ESP+2C],EAX
0007DD11   E8 76660400      CALL 000C438C
0007DD16   894424 14        MOV DWORD PTR SS:[ESP+14],EAX
0007DD1A   8B4424 10        MOV EAX,DWORD PTR SS:[ESP+10]

CMP EBX,1
JEG SHORT 0007DCEA
MOV EBX,100
On compare EBX (Dégat mini avec 1)
SI EBX<1 alors EBX=100
Les dégats mini sont de 1 au minimum (100 a cause de l'extraprécision)

CMP EBP,EBX
JG SHORT 0007DCF4
LEA EBP,DWORD PTR DS:[EBX+100]
On compare EBP et EBX (Degat max par rapport au dégat mini)
Si les degats MAx>Degat mini on passe à la suite autrement
LEA EBP,DWORD PTR DS:[EBX+100]
Un équivalent de MOV, sauf que LEA(Load effective address dont je parle dans le deuxième post)accepte les opérations. Ici c'est facile à comprendre
Degat max=Degat mini +1 au minimum (100 avec l'extraprécision donc pour les humains +1)

PUSH 19
PUSH ESI
CALL 000C438C (D2Common.dll 10519)
Bon une nouvelle propriété de l'attaquant.
STATS_DAMAGEPERCENT bref ED% (Tout sauf arme comme je vous l'ai dejà expliqué plus haut) EAX=ED%

MOV EDI,DWORD PTR SS:[ESP+24]
Un extrait de l'unité combat dont je vous ai détaillé la structure
dans le premier post sont passés sur la pile. Celui ci c'est
PhysicalDamage% (Unit+0C)
Encore un ED% mais lequel? Il faut revenir sur la section prinicpale
du combat pour comprendre. Voila comment démarre la routine
principale de combat
1) l'attaquant utilise une skill.
2) La fonction qui gère la skill s'execute. il se passe différentes
choses suivant la skill je ne rentrerais pas dans les détails.
3) Si la skill "touche" l'adversaire graphiquement, le jeu appelle la
fonction de combat et créé l'unité dégat.

Fonction de combat
1) appel de la fonction ToHit si nécessaire (dont je donne le
résultat dans Anatomie d'un combat)
2) Appel de la fonction dommage dont nous parlons
3) ...la suite nous la verrons plus tard
4) Retour à la fonction skill.

Donc jusqu'à présent c'est la skill qui provoque la création de
l'unité dégat passée sur la pile.
D'ou EDI=ED% de la skill

PUSH 12
PUSH ESI
ADD EDI,EAX
CALL 000C438C(D2Common.dll 10519)
Un peu de pipeline. On a d'un coté ADD EDI,EAX bref EDI contient
maintenant ED%(Equipement)+ ED%(skill)
Et lecture de la propriété 12 de l'attaquant (STATS_MINDAMAGE_PERCENT) Un MINED%. Actuellement aucun objet n'utilise cette propriété.

PUSH 11
PUSH ESI
MOV DWORD PTR SS:[ESP+2C],EAX
CALL 000C438C
Un peu de pipeline vous avez l'habitude maintenant.
On sauvegarde le MinED% sur la pile en position +2C
Puis on lit la propriété 11 (STATS_MAXDAMAGE_PERCENT). Bon un MaxED% même si encore une fois aucun objet ne donne cette propriété actuellement.

MOV DWORD PTR SS:[ESP+14],EAX
Sauvegarde de MaxED% sur la pile en position +14


Conclusion de la partie 3 -- Calcul des %ED
Un récapitulatif global

ESI=Pointeur de l'attaquant
EBX= Dégat mini avec extra précision
EBP= Dégat max avec extra précision
EDI= %ED (objet) + %ED (Skill)
Pile +14=%EDMax
Pile +2c=%EDMini
Bref on commence a avoir la plupart des éléments nécessaires pour la formule.



Code:
Section 4
0007DD1A   8B4424 10        MOV EAX,DWORD PTR SS:[ESP+10]
0007DD1E   85C0             TEST EAX,EAX
0007DD20   0F84 8A000000    JE 0007DDB0

On commence par un test.
Vous vous rappelez que sur la pile en +10 on a sauvegardé l'unité Arme.
Ensuite on test si on a une arme dans le cas contraire on saute à la section 4C
 
M

Myrdinn

Invité
Code:
Section 4A -- Bonus de force
0007DD26   50               PUSH EAX
0007DD27   E8 C2730400      CALL 000C50EE
0007DD2C   25 FF000000      AND EAX,0FF
0007DD31   894424 20        MOV DWORD PTR SS:[ESP+20],EAX
0007DD35   74 22            JE SHORT 0007DD59
0007DD37   6A 00            PUSH 0
0007DD39   56               PUSH ESI
0007DD3A   E8 4D660400      CALL 000C438C
0007DD3F   8BC8             MOV ECX,EAX
0007DD41   B8 1F85EB51      MOV EAX,51EB851F
0007DD46   0FAF4C24 20      IMUL ECX,DWORD PTR SS:[ESP+20]
0007DD4B   F7E9             IMUL ECX
0007DD4D   C1FA 05          SAR EDX,5
0007DD50   8BCA             MOV ECX,EDX
0007DD52   C1E9 1F          SHR ECX,1F
0007DD55   03D1             ADD EDX,ECX
0007DD57   03FA             ADD EDI,EDX

PUSH EAX
CALL 000C50EE (D2COMMON.DLL 10807)
Cette fonction n'a besoin que d'un paramètre, l'unité Arme. Elle lit
la colonne qui donne le bonus de force (colonne X sous Excel) StrBonus dans Weapons.txt (En réalité comme d'habitude à partir du .bin généré à partir du txt)
Le fichier est disponible
ici

AND EAX,000000FF Lebonus de force est uniquement dans le dernier Bytes. Ce AND passe à zero les 3 premiers bytes. C'est l'équivalent de EAX=AL si vous vous souvenez du deuxième post. J'ai un schéma si vous le souhaiter qui montre ca.
Ca permet de faire un test rapide EAX=0 et de supprimer des valeurs parasites dans les trois premiers bytes au cas ou.

MOV DWORD PTR SS:[ESP+20],EAX. On sauvegarde le bonus de force sur la pile en position +20.
JE 0007DD59 (Section 4B)
Le test se rapporte au AND. Si le résultat egal 0 alors on sort de la section 4A pou aller en 4B logique non

PUSH 0
PUSH ESI
CALL 000C438C (D2COMMON.DLL 10519)
MOV ECX,EAX
Toujours la même on récupère la propriété STATS_STRENGTH =la force de l'attaquant que l'on copie dans ECX.

MOV EAX,51EB851F
IMUL ECX,DWORD PTR SS:[ESP+20]
IMUL ECX
SAR EDX,5
MOV ECX,EDX
SHR ECX,1F
ADD EDX,ECX
Etrange. on place un nomnre supérieur à 1 milliard dans EAX???
Ensuite on multiplie ECX par ESP+20 (La force x Bonus de force)
Ensuite on pulitplie le résultat par EAX (Imul ECx) puis on applique une suite d'opération.
Le but n'étant pas de faire de l'assembleur mais de tracer la fonction je n'essayerais même pas de comprendre ce qui ce passe. Si vous tracer cette série vous verrez qu'il s'agit de la facon dont l'assembleur fait une division par 100. A partir de maintenant dès que vous verrez MOV ?,51EB851F vous saurez que c'est une division par 100
Au final EDX contient le bonus ED% grace à la force
ED%(Force)=Force x ColonneStrBonus(weapon.txt)/100
ADD EDI,EDX
On ajoute les ED%(Force) aux ED%(equipement)+ED%(Skill) dans EDI


Code:
Section 4B --Bonus de Dextérité
0007DD59   8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]
0007DD5D   52               PUSH EDX
0007DD5E   E8 85730400      CALL 000C50E8
0007DD63   25 FF000000      AND EAX,0FF
0007DD68   894424 20        MOV DWORD PTR SS:[ESP+20],EAX
0007DD6C   74 22            JE SHORT 0007DD90
0007DD6E   6A 02            PUSH 2
0007DD70   56               PUSH ESI
0007DD71   E8 16660400      CALL 000C438C
0007DD76   8BC8             MOV ECX,EAX
0007DD78   B8 1F85EB51      MOV EAX,51EB851F
0007DD7D   0FAF4C24 20      IMUL ECX,DWORD PTR SS:[ESP+20]
0007DD82   F7E9             IMUL ECX
0007DD84   C1FA 05          SAR EDX,5
0007DD87   8BC2             MOV EAX,EDX
0007DD89   C1E8 1F          SHR EAX,1F
0007DD8C   03D0             ADD EDX,EAX
0007DD8E   03FA             ADD EDI,EDX
MOV EDX,...ESP+10
PUSH EDX
CALL 000C50E8 (D2COMMON.DLL 10808)
Nouvelle fonction avec uniquement l'arme en entrée. Celle ci récupère la valeur de la colonne DexBonus dans EAX.

AND EAX,0F
MOV DWORD PTR SS:[ESP+20],EAX
JE SHORT 0007DD90 (Section 4C)
Idem on sauvegarde le bonus sur la pile, on passe à la section
suivante si le bonus est nul.

PUSH 2
PUSH ESI
CALL D2COMMON.DLL 10519
MOV ECX,EAX
On récupère la propriété STATS_Dextérity donc la dextérité dans ECX.

MOV EAX,51EB851F
...
ADD EDX,EAX
Pas la peine de rabacher on a EDX=Dextérité x Bonus DEX /100

ADD EDI,EDX
On ajoute au ED% existant on a donc
EDI=ED%(dex)+ED%(Force)+ED%(Equipement)+ED%(Skill)


Code:
Section 4C __ Bonus ED masteries
0007DD90   8B5424 10        MOV EDX,DWORD PTR SS:[ESP+10]
0007DD94   6A 00            PUSH 0
0007DD96   8D4C24 20        LEA ECX,DWORD PTR SS:[ESP+20]
0007DD9A   6A 00            PUSH 0
0007DD9C   51               PUSH ECX
0007DD9D   52               PUSH EDX
0007DD9E   6A 00            PUSH 0
0007DDA0   56               PUSH ESI
0007DDA1   C74424 34 000000>MOV DWORD PTR SS:[ESP+34],0
0007DDA9   E8 AC700400      CALL 000C4E5A
0007DDAE   EB 08            JMP SHORT 0007DDB8
On commence par récupérer l'arme dans EDX.
Je ne me rapelle plus ce qu'il y a dans ESP+20, nous en reparlerons avec le Trace.
Ensuite on fait 6 Push (O,O,Arme,?,0,Attaquant) pour la fonction
D2Common.dll 11023.
Puis on met à ZERO le dword en +34 sur la pile.
J'ai déjà tracer cette fonction mais elle est particulièrement
compliquée. Dans ce cas elle récupère le %ED de la masterie pour les barbares et assassins. Par contre elle a beaucoup d'autres fonctions qui sont toutes des extractions des skills maitrises et je ne connait pas parfaitement les paramètres en entrée.

Au final EAX=ED% Maitrise.
Puis pour finir on passe à la section 4E (7DDB8)

Code:
Section 4D -- Sans Arme
0007DDB0   6A 00            PUSH 0
0007DDB2   56               PUSH ESI
0007DDB3   E8 D4650400      CALL 000C438C
Rappelez vous le test initial en 7DD20. Si l'attaquant n'est pas armé alors on saute à cette section. autrement toute les autres sections finissent directement en 4E a partir de la ligne 7DDAE.
Sinon toujours la même fonction 10519.
Si on est à mains nues EAX=Force.


Code:
 Section 4E -- Calcul du %ED Final
0007DDB8   03F8             ADD EDI,EAX
Rappelez vous
EDI=ED%(dex)+ED%(Force)+ED%(Equipement)+ED%(Skill) ou

ED%(equip)+ED%(Skill) si on a pas d'arme.
EAX=ED% MAsteries ou STR si on à pas d'arme.

Conclusion de la section 4
EDI contient maintenant la somme des ED%

EDI=ED%(Dex)+ED%(Force)+ED%(masteries)+ED%(Skill)+ED%(Equiepement)
A mains nues les 3 premiers sont remplacés par ED%=Force.
 
M

Myrdinn

Invité
Avant de commencer un petit rappel de tous les registres et valeurs sauvegardé sur la pile

Registres
EBX= Dégats mini
EBP= Dégats maxi
EDI= Somme des ED%

PILE
+28= Dégats de base passés par la skill
+24= +Min%ED
+14= +Max%ED

Code:
 Section 5
0007DDBA   8B4424 28        MOV EAX,DWORD PTR SS:[ESP+28]
0007DDBE   85ED             TEST EBP,EBP
0007DDC0   7E 63            JLE SHORT 0007DE25
MOV EAX,DWORD PTR SS:[ESP+28]
EAX contient les dégats de base passés sur la pile par la skill au cas ou on ne rajoute pas de dégat.(=Test suivant)

Test EBP,EBP
JLE 0007DE25(Section 5C)
Si les dégats max sont <=0 alors on passe à la section 5D. pas la peine d'appliquer des % sur 0.

Code:
 Section 5A dégats mini
0007DDC2   8B4424 24        MOV EAX,DWORD PTR SS:[ESP+24]
0007DDC6   8D0C38           LEA ECX,DWORD PTR DS:[EAX+EDI]
0007DDC9   B8 1F85EB51      MOV EAX,51EB851F
0007DDCE   0FAFCB           IMUL ECX,EBX
0007DDD1   F7E9             IMUL ECX
0007DDD3   C1FA 05          SAR EDX,5
0007DDD6   8BCA             MOV ECX,EDX
0007DDD8   B8 1F85EB51      MOV EAX,51EB851F
0007DDDD   C1E9 1F          SHR ECX,1F
0007DDE0   03D1             ADD EDX,ECX
0007DDE2   03D3             ADD EDX,EBX
0007DDE4   8BDA             MOV EBX,EDX
Bref on arrive ici si on fait des dégats. Dans ce cas EAX est ecrasé par une nouvelle valeur

MOV EAX,DWORD PTR SS:[ESP+24]
LEA ECX,DWORD PTR DS:[EAX+EDI]
EAX contient Min%ED
ECX=EDI+EAX= Somme de tout les ED%+Min%ED logique.

MOV EAX,51EB851F
...
ADD EDX,ECX
On mulitplie les dégats mini par la somme des ED% (IMUL ECX,EBX)
Puis on divise le résultat par 100
Le résultat est dans EDX(=Degats mini de base * ED%)

ADD EDX,EBX
On ajoute les dégats mini EDX =(Degats mini de base * ED%)+ degats mini de base.

MOV EBX,EDX
Puis on remet le résultat dans EBX
Au final Dégats mini= "Dégats mini base + dégats mini base X ED% /100" soit l'equivalent de Dégats mini= Dégats mini de base *(1+ED%/100) toujours dans EBX

Code:
Section 5B Dégats Maxi
0007DDE6   8B5424 14        MOV EDX,DWORD PTR SS:[ESP+14]
0007DDEA   8D0C3A           LEA ECX,DWORD PTR DS:[EDX+EDI]
0007DDED   0FAFCD           IMUL ECX,EBP
0007DDF0   F7E9             IMUL ECX
0007DDF2   8B4C24 28        MOV ECX,DWORD PTR SS:[ESP+28]
0007DDF6   C1FA 05          SAR EDX,5
0007DDF9   8BC2             MOV EAX,EDX
0007DDFB   C1E8 1F          SHR EAX,1F
0007DDFE   03D0             ADD EDX,EAX
0007DE00   8D040B           LEA EAX,DWORD PTR DS:[EBX+ECX]
0007DE03   03D5             ADD EDX,EBP
0007DE05   894424 28        MOV DWORD PTR SS:[ESP+28],EAX

C'est la même chose pour les dégats Maxi
Rapidement à cause du pipeline on a la ligne 0007DDD8 qui devrait faire partie de cette section
LEs 2 premières lignes donnent au final ECX=Somme des ED% + Max%ED
Ensuite on multiplie ECX par EBP (degats de base par somme des ED%)

IMUL ECX
SAR EDX,5
MOV EAX,EDX
SHR EAX,1F
ADD EDX,EAX
Une petite division par 100, le résultat est dans EDX= DMGmax * ED%/100

les instructions suivantes appartiennent à un autre calcul (Pipeline oblige)
MOV ECX,DWORD PTR SS:[ESP+28] (Au mileu de la division par 100)
ECX=Dégats passés par la skill (CF objet dégat du post 2)
LEA EAX,DWORD PTR DS:[EBX+ECX]
EAX= Dégat mini + degats passés par la skill (N.B. EBX contient toujours les dégats mini non modifié pour la suite vous comprendrez ce notabene plus tard.)

ADD EDX,EBP
On revient à la routine de calcul des dégats max
Degats max=Degat max de base + DMGmax * ED%/100 soit DMGMax de base (1+ED%/100) stoqué dans EDX pour l'instant

MOV DWORD PTR SS:[ESP+28],EAX
On place les Dégat mini + degats passés par la skill sur la pile en +28

Code:
Section 5C -- Calcul des dégats effectifs
0007DE09   3BD3             CMP EDX,EBX
0007DE0B   7E 14            JLE SHORT 0007DE21
0007DE0D   2BD3             SUB EDX,EBX
0007DE0F   74 0A            JE SHORT 0007DE1B
0007DE11   8D4E 2C          LEA ECX,DWORD PTR DS:[ESI+2C]
0007DE14   E8 E7690400      CALL 000C4800
0007DE19   EB 02            JMP SHORT 0007DE1D
0007DE1B   33C0             XOR EAX,EAX
0007DE1D   014424 28        ADD DWORD PTR SS:[ESP+28],EAX
0007DE21   8B4424 28        MOV EAX,DWORD PTR SS:[ESP+28]

CMP EDX,EBX
JLE SHORT 0007DE21
Degats max <= Dégats Mini. Si oui passé directement à la fin de la section.

Autrement (Cas classique)
SUB EDX,EBX (EDX=DegatMax-DegatMini)
JE SHORT 0007DE1B (Si le resultat vaut 0 (Max=Mini) aller en 7DE1B)

LEA ECX,DWORD PTR DS:[ESI+2C]
CALL 000C4800(D2COMMON.DLL 10520)
Voila une autre fonction très importante de D2COMMON.DLL. L'aléatoire.
Elles prend 2 paramètres en entrée EDX et ECX (et nin des push comme

d'ahabitude).
EDX=Valeur maximum
ECX=Seed de l'unité utilisé pour la génération de la prochaine valeur aléatoire.(Cf mon post Aleatoire)
LE résultat dans EAX est un nombre entre 0 et EDX.
ICi entre 0 et (Max-Min)
JMP SHORT 0007DE1D (Flow control. eviter la prochaine ligne reservé à dégat mini = dégat max.

XOR EAX,EAX Si dégat mini = dégat max alors EAX=O sion on a passé cette partie et EAX=RANDOM(Max-Mini)

ADD DWORD PTR SS:[ESP+28],EAX
On ajoute la valeur aléatoire A DegatMini + Degat(Skill)
Bref on a au final sur la pile en +28
ESP+28=Degats effectifs=DegatMini + Dégats (skill) + RANDOM(MAx-MINI)

MOV EAX,DWORD PTR SS:[ESP+28]
Maintenant on copie les dégats effectifs actuels dans EAX


Code:
section 5D Calcul final
0007DE25   33C9             XOR ECX,ECX
0007DE27   6A 6F            PUSH 6F
0007DE29   85C0             TEST EAX,EAX
0007DE2B   0F9CC1           SETL CL
0007DE2E   49               DEC ECX
0007DE2F   56               PUSH ESI
0007DE30   23C8             AND ECX,EAX
0007DE32   8BF9             MOV EDI,ECX
0007DE34   E8 F9670400      CALL 000C4632
0007DE39   C1E0 08          SHL EAX,8
0007DE3C   03C7             ADD EAX,EDI
XOR ECX,ECX equivaut à ECX=0 Cf table de vérité de XOR
On place 6F sur la pile (Pour le prochain Call)
On test si EAX (Dégats effectifs) < 0? Dégats négatifs
Si c'est le cas CL=1
Commande SETxx A. Donne une valeur booléene à A (Vrai ou faux 1 ou 0) suivant le résultat du test précedent.
Ici la commande est SETL (Set if LEss) donc si EAX<0 alors CL=1 (Vous verrez les flag register quand nous ferons le trace)
Rappelez vous CL egal premier byte de ECX (Cx low bytes)

DEC ECX (ECX=ECX-1) (Degat négatif => ECX=0 sinon ECX=FFFFFFFF)

PUSH ESI (pointeur de l'attaquant sur la pile pour le prochain call)

AND ECX,EAX.
Bon vous aurez compris
Si dégats négatf ecx vaut 0 et donc EAX(Dégat effectif =0)
Autrement ECX=FFFFFFFF et donc AND ECX,EAX=EAX.
Conclusion Si les dégats sont inférieur à zéro les dégats = 0

MOV EDI,ECX
EDI contient désormais les dégats effectifs

CALL D2COMMON.DLL 10520. les paramètres sont les 2 derniers push 6F et ESI.
C'est la même fonction que pour 10519 sauf quelle récupère les propriété qui commencent pas STATS_ITEM
6F=STATS_ITEM_NORMALDAMAGE. Ce sont les dégats normaux qu'il ne faut pas intégré à l'arme. Aucun objet n'a cette propriété sous D2. Je l'avais activé par erreur dans mon MOD avant que Schoom ne me corrige.
SHL EAX,8 Ces dommages beneficie également de l'extra précision

ADD EAX,EDI.

Résultat final de cette fonction dans EAX=STATS_ITEM_NORMALDAMAGE + Dommage effectifs. Le tout dans EAX car comme vous le savez maintenant toutes les fonctions retourne le résultat dans EAX.

Code:
 Final
0007DE3E   5F               POP EDI
0007DE3F   5E               POP ESI
0007DE40   5D               POP EBP
0007DE41   5B               POP EBX
0007DE42   83C4 08          ADD ESP,8
0007DE45   C2 1000          RETN 10
0007DE48   90               NOP
0007DE49   90               NOP
0007DE4A   90               NOP
0007DE4B   90               NOP
0007DE4C   90               NOP
0007DE4D   90               NOP
Bon la fin est trivial c'est le complément inverse de la section 1. si vous avez des questions je suis prêt
 
M

Myrdinn

Invité
Bon récapitulons le tout

Dégats finaux=MINI+RANDOM(MAX-MINI) + Dégat(skill) + DegatsNormaux(n'existe pas pour l'instant)
avec

Dégats mini(MINI)= Dégats base mini X (1+(ED%+MIN%ED)/100)
Dégats Max(MAX)=Dégats base max X (1+(ED%+MAX%ED)/100)

Avec
ED%=ED%(force)+ED%(dextérité)+ED%(skill)+ED%(Maitrise)+ED%(Equipement autre que Arme)
Dégat de base mini= [(Degat mini de l'arme+ Booléen(ED>0?)) x (1+ED%(Arme)/100)] + Somme des "+dégats mini" de tout l'equipement (Arme inclus)
Dégats de base maxi=[(Degat max de l'arme+ Booléen(ED>0) X (1+ED%(Arme)/100)] + Somme des "+ dégats max" de tout l'equipement (Arme inclus)

P.S. L'"etheral" s'applique directement sur les dégats de base de l'arme en les multipliant par 1.5
Les malédictions,shrines,auras du paladin ... Bref tous ce qui n'est pas précisé ici s'applique sur l'ED%(Equipement) comme s'il s'agissait d'un autre équipement.


La formule finale simplifiée( En retirant l'inexistant) est DMG=Dégat X (1+ED%/100) pour mini est max

Au passage c'est la définition même de ED%, même pas besoin de faire tout ce post pour arriver a ce résultat trivial ce n'est que du bon sens. La seule chose à retenir est que les ED% s'additionnent avant d'être appliqués.
On a des dégat de base, pour les augmenter de 75% il faut multiplier par (1+75/100) par définition.



On peut également utilisé la formule de la Faq.
Minimum Damage = (Weapon Minimum Damage + (+x To Minimum Damage)) * (1 + StatsBonus + (+x% Enhanced Damage) / 100)
Maximum Damage = (Weapon Maximum Damage + (+x To Maximum Damage)) * (1 + StatsBonus + (+x % Enhanced Damage) / 100)

+x % Enhanced Damage = all non weapon ED (like in armour/helm/shield etc) and skills (like Might, Heart of Wolverine)

'+x To Minimum/Maximum Damage' = all non weapon +min/max damage. Like from charms.
bien que ce n'est pas comme ca que le jeu gère les dégats.

Maintenant je doit écrire le post sur le tracage. J'ai besoin de faire beaucoup de photo d'écran pour vous guider pas à pas, ca sera assez long.

En attendant essayez vraiment de comprendre cette partie, le prochain post concernera surtout l'outil et même si nous tracerons cette partie je ne reviendrais pas en détail sur les mécanismes de la fonction.

Normalement vous devriez avoir des questions car j'ai omis volontairement des données externes ( il me faut une petite marge de connaissance :D) sur la gestion globale des dégats physiques.

A suivre dans le prochain post ou vous manipulerez enfin un Tracage de DLL
 
M

Myrdinn

Invité
Bon j'ai de gros problème internet.
J'editerais les parties 3 4 et 5 plus tard quand j'aurais le temps et les moyens de le faire. Vous pouvez laisser vos remarques comme d'habitude.
@Hohorga et Wakestorm. Merci à vous même si vous avez interrompu le post :lol: C'est pas grave, si ma connection marchais correctement il m'aurait fallut 6 minutes pour poster le tout et pas une demi heure :( .
Bon encore une fois n'hesitez pas à me demander plus d'info si necessaire et à bientot pour la suite
 
W

wakestorm

Invité
Oups, désolé, j'ai remarqué après avoir posté :o

Je pensais comme un c*n que tu allais tout poster d'un coup en faisant plusieurs posts en oubliant *****de ***** bien ***** et très **** de 60 secondes
 
W

wakestorm

Invité
Bon, alors j'ai lu, et j'ai compris quelques trucs, mais j'ai besoin d'une petite confirmation pour un truc : les pipelines

En très schématisé,
ça donne :

je vais acheter du jambon
un chien marche dans la rue
le ciel est nuageux
un train s'arrette dans la gare
le boucher me dis bonjour

Donc, ils sont chacun sur un pipeline sauf le boucher me dit bonjour qui dépend de "je vais acheter du jambon"

Tu peux confirmer si c'est ça ? Où quelqu'un d'autre qui s'y connait bien

Merci
 
T

Tony

Invité
arf sa va trop vite. J'ai pas encore fini de lire le 2eme post :( :eek:
heureusement j'ai un bon week end de 4 jours :) pour ratraper tous ca . Merci Myrdinn pour tes posts ;)
 
P

Paul Siramy

Invité
Pour le coup du jambon, c'est ça. Sauf qu'un Pentium n'a que 2 pipelines, mais c'est ça :

je vais chez le boucher
je dis bonjour au boucher
je regarde ma montre

est plus lent pour le microprocessuer que :

je vais chez le boucher
je regarde ma montre
je dis bonjour au boucher

Parceque dans le 1er cas il faut attendre que je soit chez le boucher avant de lui dire bonjour, d'où perte de temps.

Dans le deuxième cas, je vais chez le boucher, mais pas con, pendant que j'y vais je fait quelque chose qui n'a aucun rapport : je regarde ma montre, c'est du temps de gagné ;)



A part ça, un truc tout con à savoir, mais qui aide bien à la compréhension de certains passages asm : JZ (Jump if Zero) et JE (Jump if Equal) c'est exactement la même chose. De même que JNZ (Jump if Not Zero) et JNE (Jump if Not Equal).

Quand vous lisez un JZ dans un code et que vous comprenez pas pourquoi le code fait ça, remplacer le JZ par un JE et voyez ce que ça donne. Moi je me suis fait avoir il y a 1 ou 2 mois ;)

JZ = JE
JNZ = JNE
 
M

Myrdinn

Invité
Voila les sections 3 et 4 sont mises à jour.
Il ne manque plus que la section 5 qui arrivera très vite.
C'est la plus intérressantes, car elle donne LA FORMULE qui utilise les résultats des autres sections.
Dès que je l'auris éditée vous pourrez envoyer un MP a Kalis pour qu'il corrige la FAQ et la formule obsolète.

Total Damage:
Minimum Damage = (Weapon Minimum Damage + (+x To Minimum Damage)) * (1 + StatsBonus + (+x% Enhanced Damage) / 100)
Maximum Damage = (Weapon Maximum Damage + (+x To Maximum Damage)) * (1 + StatsBonus + (+x % Enhanced Damage) / 100)

+x % Enhanced Damage = all non weapon ED (like in armour/helm/shield etc) and skills (like Might, Heart of Wolverine)

'+x To Minimum/Maximum Damage' = all non weapon +min/max damage. Like from charms.

You calculate your Weapon Minimum/Maximum damage with this formula :

Weapon Damage:
Weapon Minimum Damage = (Base Minimum Damage+1) * (1+ (+x % Enhanced Damage)/100) + (+x to Minimum Damage)
Weapon Maximum Damage = (Base Maximum Damage+1) * (1+ (+x % Enhanced Damage)/100) + (+x to Maximum Damage)

+x % Enhanced Damage and +x to Minimum/Maximum Damage = The mods on the weapon.

Statsbonus : Remember more str increases damage, however some weapons are affected differently.

Maces: 1.10 x str / 100
Daggers, Throwing Weapons (and Assassin Claws) : (0.75 x str + 0.75 x dex) / 100
Bows/ Xbows : dex / 100
Other Weapons : str / 100




P.S. Merci Paul (Comme toujours) pour les précisions que tu as donné en mon absence. Il y a peu de chance que j'ai quelque chose à t'apprendre ;)
 
H

hohorga

Invité
Provient du message de Myrdinn
.
@Hohorga et Wakestorm. Merci à vous même si vous avez interrompu le post :lol:

Désolé je ne pensais pas que tu en mettrais autant :o
 
M

Myrdinn

Invité
Bon voila le post est terminé, je serais surement amené à editer suivant vos remarques. n'hesitez pas à me poser des questions car ce post est important pour votre premier tracage.

@Hohorga et Wakestorm. Y a pas de mal, avec un peu de chance ca donne envie au lecteur de continuer :lol:

@Wakestorm. Paul a répondu a ta demande pour l'hexadécimal dans mon premier post sur les Dlls. Si tu as besoin d'un lien ou si tu as une question précise n'hesite pas. Et puis la calculatrice windows fait la conversion pour toi, si tu en as besoin
 
K

kaizel

Invité
Provient du message de Myrdinn

@Hohorga et Wakestorm. Merci à vous même si vous avez interrompu le post :lol:
c'est pour cela que j'attend toujours avant de repondre au post de myrdinn franchement je dois avoué la que je suis pommé ....
sinon bravo myrdinn encore une fois meme si la je capte rien :D
 
M

Myrdinn

Invité
JE peux essayer de t'aider si tu le veux. Sans des bonnes bases en info il est très dur de tout vous expliquer en 3 Sujets.

Cependant je donne la formule dans la partie conclusion (qui elle ne contient pas d'assembleur) pourra toujours te servir d'autant qu'elle est inédite à ma connaissance :D
 
Haut