如您所知,在每个小酒馆的这一系列游戏中,玩家每周只能租用一个新英雄。但…
错误说明: 如果外部酒馆中没有招募人员,那么从第8天开始,您可以在两天内购买两个英雄。
最新的官方插件“ Winds of War”中的反汇编文件heroes4.exe用于工作。小酒馆的操作程序是由团队较早发现的,位于地址4705E0。从其工作的整个算法来看,我对确定是否可以在小酒馆中现在雇用英雄或是否有必要等待的地方感兴趣。在游戏中,这通过相应消息的输出来体现:
从程序的角度来看,这是一个在游戏中使用NewWindowCreate(720C80)函数创建的新窗口(在反汇编程序中识别的函数具有自己的名称)。在酒馆的过程中有多次对该函数的调用,第一个挑战者是对地址470823的调用。在调试器的帮助下,我确保实际上此调用会创建所需的对话框。控制对NewWindowCreate的调用的代码位于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
我买了英雄的酒馆,然后将“断点”设置为写入[ebp + 48h]的单元格,此后我要等待7天。当小酒馆被“清空”时,调试器以470DFF弹出。让我们看看周围的代码:
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
这个小程序用于检查小酒馆关闭出租的天数。请注意,每个游戏日在地图上的每个小酒馆都会调用它。是什么导致该错误?由于某种原因,该程序会继续计算在酒馆中没有英雄招聘的天数以及在酒馆关闭一周后的天数(请参见470E06处的计数器)。结果,我们得到以下图片。让英雄的第一次征募仅在比赛第八天进行。在该过程的入口处,在[ecx + 48h]的小酒馆可用性标志的值将等于“ 1”(小酒馆关闭),并且在[ecx + 4Ch]的日计数器的值将等于“ 8”。但是,在470DF9进行比较之后,控件将在470DFF处收到代码,这将重新打开小酒馆以供租用!这将重置日计数器。在雇用第二位Hero之后,该算法将按照作者的预期进行计算。但是在游戏中的两个星期之后,整个循环将重复进行。
解决该错误的最简单方法是跳过计算日期。让计数器仅在小酒馆关闭(更合乎逻辑)时起作用,其余时间将其设置为零。这可以非常简单地实现-通过将地址00470DF7的转换更改为函数的结尾:
00470DF5 cmp dl, al
00470DF7 jz short loc_470E09
现在剩下的就是修补现有代码。为此,请看原始
并修改
选项。
如您所见,可以通过在地址470DF8上将0D替换为10来获得所需的结果。该类型的经典作品:只需替换一个字节即可修补错误!