Comme vous le savez, dans cette série de jeux dans chaque taverne, le joueur ne peut embaucher qu'un nouveau héros par semaine. Mais…
Description du bug: s'il n'y a pas eu de recrutement dans la taverne externe, à partir du 8ème jour, vous pouvez acheter deux héros en deux jours.
Le fichier désassemblé heroes4.exe du dernier addon officiel "Winds of War" est utilisé pour le travail. La procédure de fonctionnement de la taverne a été trouvée par l'équipe plus tôt et se trouve à l'adresse 4705E0. De l'ensemble de l'algorithme de son travail, je m'intéresse au lieu dans lequel il est déterminé s'il est possible d'embaucher un héros dans la taverne pour le moment, ou s'il faut attendre. Dans le jeu, cela se manifeste par la sortie du message correspondant:
D'un point de vue programmatique, il s'agit d'une nouvelle fenêtre créée dans le jeu à l'aide de la fonction NewWindowCreate (720C80) (les fonctions reconnues dans le désassembleur reçoivent leurs propres noms). Il y a plusieurs appels à cette fonction dans la procédure de la taverne, et le premier challenger est un appel à l'adresse 470823. Avec l'aide du débogueur, je m'assure qu'en fait, cet appel crée la boîte de dialogue souhaitée. Le code qui contrôle cet appel à NewWindowCreate est situé ci-dessus à 470645:
00470638 call HeroesPricesInTavern_Lost
0047063D mov al, [ebp+48h] // 0 – ; 1 – ( 7 ).
00470640 add esp, 8
00470643 test al, al
00470645 jz loc_470866 // , 470823
J'achète dans la taverne du héros, puis je règle le "point d'arrêt" pour écrire dans la cellule adressée à [ebp + 48h], après quoi j'attends 7 jours de jeu. Lorsque la taverne est "vidée", le débogueur apparaît à l'adresse 470DFF. Voyons le code environnant:
00470DF0 TavernCountDays proc near
00470DF0 mov dl, [ecx+48h] // ECX+48h – :
DL=0 – ;
DL=1 – ( 7 )
00470DF3 xor eax, eax
00470DF5 cmp dl, al
00470DF7 jz short loc_470E06
00470DF9 cmp dword ptr [ecx+4Ch], 7 // [ECX+4Ch] - . 7 – .
00470DFD jl short loc_470E06
00470DFF mov [ecx+48h], al // (AL=0)
00470E02 mov [ecx+4Ch], eax //
00470E05 retn
00470E06
00470E06 loc_470E06:
00470E06
00470E06 inc dword ptr [ecx+4Ch] //
00470E09 retn
00470E09 TavernCountDays endp
Cette petite procédure permet de vérifier le nombre de jours de fermeture de la taverne à la location. Notez qu'il est appelé pour chaque taverne sur la carte chaque jour de match. Qu'est-ce qui cause le bogue? Pour une raison quelconque, le programme continue de compter le nombre de jours pendant lesquels le héros n'a pas été embauché dans la taverne et après la semaine où la taverne a été fermée (voir le compteur à 470E06). En conséquence, nous obtenons l'image suivante. Que le premier recrutement du héros n'ait lieu que le huitième jour de match. A l'entrée de la procédure, la valeur du drapeau de disponibilité de la taverne à [ecx + 48h] sera égale à "1" (la taverne est fermée), et la valeur du compteur de jour à [ecx + 4Ch] sera égale à "8". Cependant, après la comparaison à 470DF9, le contrôle recevra un code à 470DFF, qui rouvre la taverne à la location! Cela réinitialisera le compteur du jour.et après avoir embauché le deuxième héros, l'algorithme fonctionnera déjà , comme les auteurs l'avaient prévu. Mais après deux semaines de jeu, tout le cycle se répétera.
Le moyen le plus simple de corriger le bogue est d'arrêter de compter les jours. Laissez le compteur fonctionner uniquement lorsque la taverne est fermée (ce qui est plus logique), et le reste du temps, nous le mettons à zéro. Ceci est réalisé très simplement - en modifiant la transition à l'adresse 00470DF7 vers la fin de la fonction:
00470DF5 cmp dl, al
00470DF7 jz short loc_470E09
Il ne reste plus qu'Ă patcher le code existant. Pour ce faire, regardez l'original
et modifié
options.
Comme vous pouvez le voir, le résultat souhaité peut être obtenu en remplaçant 0D par 10 à l'adresse 470DF8. Un classique du genre: corrigez un bug en remplaçant un seul octet!