
Wie Sie wissen, kann der Spieler in dieser Reihe von Spielen in jeder Taverne nur einen neuen Helden pro Woche einstellen. Aber…
Fehlerbeschreibung: Wenn in der externen Taverne keine Rekrutierung stattgefunden hat, können Sie ab dem 8. Tag innerhalb von zwei Tagen zwei Helden kaufen.
Die zerlegte Datei Heroes4.exe aus dem neuesten offiziellen Addon "Winds of War" wird für die Arbeit verwendet. Das Tavernenbetriebsverfahren wurde vom Team früher gefunden und befindet sich unter der Adresse 4705E0. Nach dem gesamten Algorithmus seiner Arbeit interessiert mich der Ort, an dem festgestellt wird, ob es derzeit möglich ist, einen Helden in der Taverne zu mieten, oder ob es notwendig ist, zu warten. Im Spiel manifestiert sich dies in der Ausgabe der entsprechenden Nachricht:

Aus programmatischer Sicht ist dies ein neues Fenster, das im Spiel mit der Funktion NewWindowCreate (720C80) erstellt wird (die im Disassembler erkannten Funktionen erhalten ihre eigenen Namen). Es gibt mehrere Aufrufe dieser Funktion in der Prozedur der Taverne, und der erste Herausforderer ist ein Aufruf an die Adresse 470823. Mit Hilfe des Debuggers stelle ich sicher, dass dieser Aufruf tatsächlich das gewünschte Dialogfeld erstellt. Der Code, der diesen Aufruf von NewWindowCreate steuert, befindet sich oben unter 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
Ich kaufe in der Taverne des Helden und setze dann den "Haltepunkt", um in die an [ebp + 48h] adressierte Zelle zu schreiben. Danach warte ich 7 Tage im Spiel. Wenn die Taverne "geleert" ist, erscheint der Debugger unter der Adresse 470DFF. Sehen wir uns den umgebenden Code an:
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
Diese kurze Prozedur überprüft die Anzahl der Tage, an denen die Taverne zur Miete geschlossen ist. Beachten Sie, dass es an jedem Spieltag für jede Taverne auf der Karte aufgerufen wird. Was verursacht den Fehler? Aus irgendeinem Grund zählt das Programm weiterhin die Anzahl der Tage, an denen der Held nicht in der Taverne eingestellt wurde und nach der Woche, in der die Taverne geschlossen wurde (siehe Schalter bei 470E06). Als Ergebnis erhalten wir das folgende Bild. Lassen Sie die erste Rekrutierung des Helden erst am achten Spieltag stattfinden. Am Eingang des Verfahrens ist der Wert des Tavernenverfügbarkeitsflags bei [ecx + 48h] gleich "1" (die Taverne ist geschlossen) und der Wert des Tageszählers bei [ecx + 4Ch] gleich "8". Nach dem Vergleich bei 470DF9 erhält die Steuerung jedoch bei 470DFF einen Code, der die Taverne zum Mieten wieder öffnet! Dadurch wird der Tageszähler zurückgesetzt.und nach der Einstellung des zweiten Helden wird der Algorithmus bereits wie von den Autoren beabsichtigt funktionieren. Aber nach zwei Wochen im Spiel wiederholt sich der gesamte Zyklus.
Der einfachste Weg, um den Fehler zu beheben, besteht darin, die Tage nicht mehr zu zählen. Lassen Sie den Zähler nur funktionieren, wenn die Taverne geschlossen ist (was logischer ist), und den Rest der Zeit setzen wir ihn auf Null. Dies wird sehr einfach erreicht - durch Ändern des Übergangs an der Adresse 00470DF7 zum Ende der Funktion:
00470DF5 cmp dl, al
00470DF7 jz short loc_470E09
Jetzt müssen Sie nur noch den vorhandenen Code patchen. Schauen Sie sich dazu das Original an

und modifiziert

Optionen.
Wie Sie sehen können, kann das gewünschte Ergebnis erzielt werden, indem 0D durch 10 an der Adresse 470DF8 ersetzt wird. Ein Klassiker des Genres: Beheben Sie einen Fehler, indem Sie nur ein Byte ersetzen!