BugMF,就是指对暗黑各个场景最后的BOSS的特殊杀法,具有任务掉落。例如对于Baal,可以由一个已经完成Baal任务的角色首先创建游戏,由一个还未完成Baal任务的角色杀死Baal。由于这个游戏无法完成Baal任务,但是Baal仍然按照任务掉落,所以可以获得较好的掉落。
已知各个场景最后的BOSS都可以BugMF。
我们看看这个bug是如何产生的:
.text:6FC5F36A call GetPlayerCurrentQuestRecord ; ecx=1 eax=ptPlayer edx=ptGame
.text:6FC5F36F mov ebx, eax
.text:6FC5F371 test ebx, ebx
.text:6FC5F373 jz short loc_6FC5F3C7
.text:6FC5F375 movzx eax, byte ptr [ebp+9Eh] ; quest,0E=7个古墓
.text:6FC5F37C push 0Fh
.text:6FC5F37E push eax
.text:6FC5F37F push ebx
.text:6FC5F380 call D2Common_10753_GetQuestFlag ; 检查玩家是否已经完成该任务
.text:6FC5F385 cmp eax, 1
.text:6FC5F388 jz short loc_6FC5F3C7
.text:6FC5F38A movzx ecx, byte ptr [ebp+9Eh]
.text:6FC5F391 push 1
.text:6FC5F393 push ecx
.text:6FC5F394 push ebx
.text:6FC5F395 call D2Common_10753_GetQuestFlag ; 检查该任务是否奖励中?
.text:6FC5F39A cmp eax, 1
.text:6FC5F39D jz short loc_6FC5F3C7
.text:6FC5F39F movzx edx, byte ptr [ebp+9Fh]
.text:6FC5F3A6 movzx eax, byte ptr [ebp+9Eh]
.text:6FC5F3AD push edx
.text:6FC5F3AE push eax
.text:6FC5F3AF push ebx
.text:6FC5F3B0 call D2Common_10753_GetQuestFlag ; 检查该任务是否可以进行任务掉落
.text:6FC5F3B5 cmp eax, 1 ; 非BUG,EAX=1
.text:6FC5F3B8 jz short loc_6FC5F3C7
.text:6FC5F3BA mov cx, [ebp+edi*8+8Ch] ; 将任务TC作为最终选择的TC
.text:6FC5F3C2 mov word ptr [esp+64h+var_54], cx
非常清楚,GetPlayerCurrentQuestRecord将把玩家的完成任务的状态作为查询对象来决定是否进行任务TC掉落。这个和游戏的初始设定相违背。即使在一个无法完成该任务的游戏里,由于玩家并没有完成该任务,所以会按照任务掉落。
解决的方法很简单,就是将6FC5F3B0 call D2Common_10753_GetQuestFlag替换为一个进行额外检查的函数。具体实现如下:
MFBugFix proc
; 使用ptGame的QuestRecord进行检查
pop eax
pop ecx
pop ebx
pop edx
push eax ; ret addr
orig_code:
push edx
push ebx
push ecx
call D2Common_10753_GetQuestFlag
cmp eax,1
jz over
;get the ptGame->ptQuest
mov ecx,[esp+28h]
mov eax,[ecx+10F4h]
mov ebx,[eax+0Ch]
test ebx,ebx
jz over
movzx eax, byte ptr [ebp+9Eh]
push 0Fh
push eax
push ebx
call D2Common_10753_GetQuestFlag ; 任务已经完成?
cmp eax,1
jz over
movzx ecx, byte ptr [ebp+9Eh]
push 1
push ecx
push ebx
call D2Common_10753_GetQuestFlag ; 任务奖励中?
cmp eax,1
jz over
movzx edx, byte ptr [ebp+9Fh]
movzx ecx, byte ptr [ebp+9Eh]
push edx
push ecx
push ebx
call D2Common_10753_GetQuestFlag ;可以进行任务Drop?
over:
ret
MFBugFix endp
MFBugFix函数将使用ptGame的QuestRecord进行额外的任务掉落检查,将这个函数替换掉6FC5F3B1处的 call D2Common_10753_GetQuestFlag,就可以实现按照游戏的任务状态进行掉落,而不是按照玩家的任务状态进行掉落。
这个修正只是对是否进行任务掉落进行修正,不会影响游戏的其他设定。
附:GetPlayerCurrentQuestRecord
.text:6FC21CD0 GetPlayerCurrentQuestRecord proc near ; CODE XREF: sub_6FC3B040+136p
.text:6FC21CD0 ; ObjectOperateFn53+104p ...
.text:6FC21CD0 push eax
.text:6FC21CD1 call D2Common_10800_GetpPlayerDataFromUnit
.text:6FC21CD6 mov ecx, [esp+4] ; ptGame
.text:6FC21CDA movzx edx, byte ptr [ecx+6Dh]
.text:6FC21CDE mov eax, [eax+edx*4+10h] ; ((ptUnit(player)+70)+难度*4+10)+00
.text:6FC21CE2 retn 4
.text:6FC21CE2 GetPlayerCurrentQuestRecord endp |