植物大战僵尸中文第二版和年度版 游戏分析及delphi源码

00413184 |. E8 77E30100 |CALL PlantsVs.00431500 ; 地上的物品

00413189 |. 8D7424 10 |LEA ESI,DWORD PTR SS:[ESP+10]

0041318D |. 8BD3 |MOV EDX,EBX

0041318F |. E8 7C980000 |CALL PlantsVs.0041CA10

00413194 |. 84C0 |TEST AL,AL

00413196 |.^ 75 E8 \JNZ SHORT PlantsVs.00413180

00413198 |> 8D7424 10 LEA ESI,DWORD PTR SS:[ESP+10]

0041319C |. 8BD3 MOV EDX,EBX

0041319E |. 896C24 10 MOV DWORD PTR SS:[ESP+10],EBP

004131A2 |. E8 C9980000 CALL PlantsVs.0041CA70

004131A7 |. 84C0 TEST AL,AL

004131A9 |. 74 1E JE SHORT PlantsVs.004131C9

004131AB |. EB 03 JMP SHORT PlantsVs.004131B0

004131AD | 8D49 00 LEA ECX,DWORD PTR DS:[ECX]

004131B0 |> 8B4424 10 /MOV EAX,DWORD PTR SS:[ESP+10]

004131B4 |. 50 |PUSH EAX

004131B5 |. E8 26550400 |CALL PlantsVs.004586E0

004131BA |. 8D7424 10 |LEA ESI,DWORD PTR SS:[ESP+10]

004131BE |. 8BD3 |MOV EDX,EBX

004131C0 |. E8 AB980000 |CALL PlantsVs.0041CA70

004131C5 |. 84C0 |TEST AL,AL

004131C7 |.^ 75 E7 \JNZ SHORT PlantsVs.004131B0

004131C9 |> 8Bc3 3C010000 MOV EDI,DWORD PTR DS:[EBX+13C] ; edi = 游戏基址

004131CF |. E8 CC5B0200 CALL PlantsVs.00438DA0

004131D4 |. 8BB3 38010000 MOV ESI,DWORD PTR DS:[EBX+138]

004131DA |. E8 A1550200 CALL PlantsVs.00438780

004131DF |. 8B83 44010000 MOV EAX,DWORD PTR DS:[EBX+144]

004131E5 |. 33F6 XOR ESI,ESI

004131E7 |. 3968 24 CMP DWORD PTR DS:[EAX+24],EBP

004131EA |. 7E 1E JLE SHORT PlantsVs.0041320A

004131EC |. 33FF XOR EDI,EDI

004131EE |. 8BFF MOV EDI,EDI

004131F0 |> 8D4407 28 /LEA EAX,DWORD PTR DS:[EDI+EAX+28]

004131F4 |. E8 57400700 |CALL PlantsVs.00487250

004131F9 |. 8B83 44010000 |MOV EAX,DWORD PTR DS:[EBX+144]

004131FF |. 83C6 01 |ADD ESI,1

00413202 |. 83C7 50 |ADD EDI,50

00413205 |. 3B70 24 |CMP ESI,DWORD PTR DS:[EAX+24]

00413208 |.^ 7C E6 \JL SHORT PlantsVs.004131F0

0041320A |> 5F POP EDI

0041320B |. 5E POP ESI

0041320C |. 5D POP EBP

0041320D |. 83C4 08 ADD ESP,8

00413210 \. C3 RETN

00410A94 |. 52 PUSH EDX ; -1

00410A95 |. 50 PUSH EAX ; 植物类型

00410A96 |. 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20] ; Y

00410A9A |. 57 PUSH EDI ; X

00410A9B |. 55 PUSH EBP ; 游戏基址

00410A9C |. E8 7FC6FFFF CALL PlantsVs.0040D120

修改器代码:

var
Form1: TForm1;
pGameBase:Pointer;
pPlantBaseArray:array[0..100] of pointer;
pMonBaseArray:array[0..100] of pointer;
pGoodsBaseArray:array[0..100] of pointer;
   pPlantToolBarBaseArray:array[0..100] of pointer;
type
stMonsterInfo = record
x:single;
y:single;
nMaxHP:integer;
nCurHP:integer;
nRow:integer;
fSize:single;
end;

type
stPlantToolBarInfo = record
nType:integer;
nMaxRecovery:integer;
nCurRecovery:integer;
end;

type
stGoodsInfo = record
nType:integer;
end;

type
stPlantInfo = record
bIsProdure:integer;
nType:integer;
end;

implementation

{$R *.dfm}

procedure GetGameBase();
begin
asm
    pushad
    mov eax, $6a9ec0
    mov eax, [eax]
    add eax, $768
    mov eax, [eax]

    mov pGameBase, eax //游戏基址
    popad
end;
end;

function GetMonsterBase(pMonBase:Pointer):Pointer;
begin
asm
    pushad
    mov esi, pMonBase

    mov edx, pGameBase//游戏基址
    mov edi, $0041C8F0
    call edi//获取一个怪物地址

    popad
end;

Result:= Pointer(pMonBase^);
end;


function GetPlantBase(pPlantBase:Pointer):Pointer;
begin
asm
    pushad
    mov esi, pPlantBase

    mov edx, pGameBase//游戏基址
    mov edi, $0041C950
    call edi//获取一个植物地址

    popad
end;

Result:= Pointer(pPlantBase^);
end;

function GetGoodsBase(pGoodsBase:Pointer):Pointer;
begin
asm
    pushad
    mov esi, pGoodsBase

    mov edx, pGameBase//游戏基址
    mov edi, $0041CA10
    call edi//获取一个植物地址

    popad
end;

Result:= Pointer(pGoodsBase^);
end;

function GetPlantToolbarBase(nIndex:integer):Pointer;
var
pBase:Pointer;
n:integer;

begin
n:= nIndex * $50 + $28;
asm
pushad
    mov eax, pGameBase
    mov eax, [eax + $144]
    mov pBase, eax
popad
end;

pBase:= Pointer(DWORD(pBase) + n);
Result:= pBase;
end;

function GetMaxPlantNum():integer;
var
n:integer;
begin
asm
    pushad
    mov eax, pGameBase
    mov eax, [eax + $144]
    mov eax, [eax + $24]
    mov n, eax
    popad
end;

Result:= n;
end;

procedure FreshMonsterList();
var
pMonBase:Integer;
n, nIndex:integer;

begin
nIndex:= 0;
pMonBase:= 0;
n:= form1.RzComboBox1.ItemIndex;
form1.RzComboBox1.Clear;
repeat
    pMonBase:= Integer(GetMonsterBase(@pMonBase));
    if pMonBase = -1 then
    begin
      form1.RzComboBox1.ItemIndex:= n;
      exit;
    end;
    form1.RzComboBox1.Add('怪物:' + IntToStr(nIndex + 1)) ;
    pMonBaseArray[nIndex]:= Pointer(pMonBase);
    nIndex:= nIndex + 1;
until(false);
form1.RzComboBox1.ItemIndex:= n;
end;

procedure FreshPlantToolBarList();
var
nMaxPlant:integer;
i:integer;
pPlantBase:Pointer;
n, nIndex:integer;

begin
n:= form1.RzComboBox2.ItemIndex;

form1.RzComboBox2.Clear;
nIndex:= 0;
nMaxPlant:= GetMaxPlantNum();
for i:= 0 to nMaxPlant - 1 do
begin
    pPlantBase:= GetPlantToolbarBase(i);
    pPlantToolBarBaseArray[nIndex]:= pPlantBase;
    nIndex:= nIndex + 1;
    form1.RzComboBox2.Add('植物栏:' + IntToStr(nIndex));
end;

form1.RzComboBox2.ItemIndex:= n;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
GetGameBase();
end;

procedure FreshPlantList();
var
pPlantBase:Integer;
n, nIndex:integer;

begin
n:= form1.RzComboBox4.ItemIndex;
form1.RzComboBox4.Clear;
nIndex:= 0;
pPlantBase:= 0;

repeat
    pPlantBase:= Integer(GetPlantBase(@pPlantBase));
    if pPlantBase = -1 then
    begin
      form1.RzComboBox4.ItemIndex:= n;
      exit;
    end;

    form1.RzComboBox4.Add('植物:' + IntToStr(nIndex + 1)) ;
    pPlantBaseArray[nIndex]:= Pointer(pPlantBase);
    nIndex:= nIndex + 1;
until(false);
end;

procedure FreshGoodsList();
var
pGoodsBase:Integer;
cItem:TListItem;
n, nIndex:integer;

begin
n:= form1.RzComboBox3.ItemIndex;
form1.RzComboBox3.Clear;
nIndex:= 0;
pGoodsBase:= 0;

repeat
    pGoodsBase:= Integer(GetGoodsBase(@pGoodsBase));
    if pGoodsBase = -1 then
    begin
      form1.RzComboBox3.ItemIndex:= n;
      exit;
    end;
    form1.RzComboBox3.Add('物品:' + IntToStr(nIndex + 1)) ;
    pGoodsBaseArray[nIndex]:= Pointer(pGoodsBase);
    nIndex:= nIndex + 1;
until(false);
end;

procedure TForm1.TabSheet2Show(Sender: TObject);
begin
form1.RzComboBox1.Clear;
FreshMonsterList();
if form1.RzComboBox1.Items.Count > 0 then
   form1.RzComboBox1.ItemIndex:= 0;
end;

procedure TForm1.TabSheet5Show(Sender: TObject);
begin
FreshGoodsList();
if form1.RzComboBox3.Items.Count > 0 then
form1.RzComboBox3.ItemIndex:= 0;
end;

procedure TForm1.TabSheet4Show(Sender: TObject);
begin
FreshPlantList();
if form1.RzComboBox4.Items.Count > 0 then
form1.RzComboBox4.ItemIndex:= 0;
end;

procedure SetMonsterInfo(pMonBase:Pointer; stMonInfo:stMonsterInfo);
var
s:single;

begin
s:= stMonInfo.fSize;
asm
    pushad
    mov eax, pMonBase
    mov ecx, stMonInfo.x
    mov [eax + $2c], ecx

    mov ecx, stMonInfo.y
    mov [eax + $30], ecx

    mov ecx, stMonInfo.nCurHP
    mov [eax + $C8], ecx

    mov ecx, stMonInfo.nMaxHP
    mov [eax + $cc], ecx

    mov ecx, stMonInfo.nRow
    mov [eax + $1c], ecx

    mov ecx, stMonInfo.fSize
    mov [eax + $11c], ecx
    popad
end;
end;

procedure GetMonsterInfo(pMonBase:Pointer;stMonInfo:stMonsterInfo);
var
x:single;
y:single;
nMaxHP:integer;
nCurHP:integer;
nRow:integer;
fSize:single;
begin
asm
    pushad
    mov eax, pMonBase
    mov ecx, [eax + $2c]
    mov x, ecx

    mov ecx, [eax + $30]
    mov y, ecx

    mov ecx, [eax + $c8]
    mov nCurHP, ecx

    mov ecx, [eax + $cc]
    mov nMaxHP, ecx

    mov ecx, [eax + $1c]
    mov nRow, ecx

    mov ecx, [eax + $11c]
    mov fSize, ecx
    popad
end;


form1.RzEdit5.Text:= FloatToStr(x);
form1.RzEdit5.Text:= FloatToStr(x);
form1.RzEdit6.Text:= FloatToStr(y);
form1.RzEdit7.Text:= IntToStr(nMaxHP);
form1.RzEdit8.Text:= IntToStr(nCurHP);
form1.RzEdit9.Text:= IntToStr(nRow);
form1.RzEdit10.Text:= FloatToStr(fSize);
end;

procedure TForm1.RzButton4Click(Sender: TObject);
var
pMonBase:Pointer;
stInfo:stMonsterInfo;
nIndex:integer;
begin
if form1.RzComboBox1.Items.Count <= 0 then
    exit;
nIndex:= form1.RzComboBox1.ItemIndex;
FreshMonsterList();
pMonBase:= Pointer(pMonBaseArray[nIndex]);

stInfo.x:= StrToFloat(form1.RzEdit5.Text);
stInfo.y:= StrToFloat(form1.RzEdit6.Text);
stInfo.nMaxHP:= StrToInt(form1.RzEdit7.Text);
stInfo.nCurHP:= StrToInt(form1.RzEdit8.Text);
stInfo.nRow:= StrToInt(form1.RzEdit9.Text);
stInfo.fSize:= StrToFloat(form1.RzEdit10.Text);

nIndex:= form1.RzComboBox1.ItemIndex;
FreshMonsterList();
pMonBase:= Pointer(pMonBaseArray[nIndex]);
SetMonsterInfo(pMonBase, stInfo);

end;

procedure TForm1.RzComboBox1Change(Sender: TObject);
var
stInfo:stMonsterInfo;
pMonBase:pointer;
nIndex:integer;

begin
   if form1.RzComboBox1.Items.Count <= 0 then
    exit;
nIndex:= form1.RzComboBox1.ItemIndex;
FreshMonsterList();
pMonBase:= Pointer(pMonBaseArray[nIndex]);
GetMonsterInfo(pMonBase, stInfo);

end;

procedure TForm1.RzComboBox1CloseUp(Sender: TObject);
begin
FreshMonsterList();
end;

procedure SetGoodsInfo(pGoodsBase:Pointer; stInfo:stGoodsInfo);
var
nType:integer;

begin
nType:= stInfo.nType;
asm
    pushad
    mov eax, pGoodsBase

    mov ecx, nType
    mov [eax + $58], ecx
    popad
end;
end;

procedure GetGoodsInfo(pGoodsBase:Pointer; var stInfo:stGoodsInfo);
var
nType:integer;

begin
asm
    pushad
    mov eax, pGoodsBase
    mov ecx, [eax + $58]
    mov nType, ecx
    popad
end;

   form1.RzEdit4.Text:= IntToStr(nType);
end;

procedure TForm1.TabSheet3Show(Sender: TObject);
begin
FreshPlantToolBarList();
if form1.RzComboBox2.Items.Count > 0 then
    form1.RzComboBox2.ItemIndex:= 0;
end;

procedure TForm1.RzComboBox3Change(Sender: TObject);
var
stInfo:stGoodsInfo;
pGoodsBase:pointer;
nIndex:integer;

begin
   if form1.RzComboBox3.Items.Count <= 0 then
    exit;
nIndex:= form1.RzComboBox3.ItemIndex;
FreshGoodsList();
pGoodsBase:= Pointer(pGoodsBaseArray[nIndex]);
GetGoodsInfo(pGoodsBase, stInfo);
end;

procedure TForm1.RzButton3Click(Sender: TObject);
var
stInfo:stGoodsInfo;
nIndex:integer;
pGoodsBase:Pointer;

begin
    if (form1.RzComboBox3.Items.Count <= 0) and (StrToInt(form1.RzEdit4.Text) <= 15) then
    exit;

nIndex:= form1.RzComboBox3.ItemIndex;
FreshGoodsList();
pGoodsBase:= Pointer(pGoodsBaseArray[nIndex]);
// ShowMessage(IntToStr(DWORD(pGoodsBase)));
stInfo.nType:= StrToInt(form1.RzEdit4.Text);
SetGoodsInfo(pGoodsBase, stInfo);
end;

procedure GetPlantInfo(pPlantBase:Pointer; var stInfo:stPlantInfo);
var
bIsProdure:integer;
nType:integer;

begin
asm
    pushad
    mov eax, pPlantBase
    mov ecx, [eax + $28]
    mov bIsProdure, ecx

    mov ecx, [eax + $24]
    mov nType, ecx
    popad
end;

   form1.RzEdit3.Text:= IntToStr(bIsProdure);
   form1.RzEdit2.Text:= IntToStr(nType);
end;

procedure SetPlantInfo(pPlantBase:Pointer; stInfo:stPlantInfo);
var
bIsProdure:integer;
nType:integer;

begin
bIsProdure:= stInfo.bIsProdure;
nType:= stInfo.nType;
asm
    pushad
    mov eax, pPlantBase
    mov ecx, bIsProdure
    mov [eax + $24], ecx

    mov ecx, nType
    mov [eax + $28], ecx
    popad
end;
end;

procedure TForm1.RzComboBox4Change(Sender: TObject);
var
stInfo:stPlantInfo;
pPlantBase:pointer;
nIndex:integer;

begin
if form1.RzComboBox4.Items.Count <= 0 then
    exit;
nIndex:= form1.RzComboBox4.ItemIndex;
FreshPlantList();
pPlantBase:= Pointer(pPlantBaseArray[nIndex]);
GetPlantInfo(pPlantBase, stInfo);
end;

procedure TForm1.RzButton2Click(Sender: TObject);
var
stInfo:stPlantInfo;
nIndex:integer;
pPlantBase:Pointer;

begin
if (MessageBox(form1.Handle, '该功能可能会引起不良效果,请确定要不要使用?使用前请先保存游戏!!', '提示', Windows.MB_ICONWARNING or MB_YESNO) = IDNO) then
    exit;

if (form1.RzComboBox4.Items.Count <= 0) then
    exit;

nIndex:= form1.RzComboBox4.ItemIndex;
FreshPlantList();
pPlantBase:= Pointer(pPlantBaseArray[nIndex]);
// ShowMessage(IntToStr(DWORD(pGoodsBase)));
stInfo.bIsProdure:= StrToInt(form1.RzEdit3.Text);
stInfo.nType:= StrToInt(form1.RzEdit2.Text);
SetPlantInfo(pPlantBase, stInfo);
end;

procedure TForm1.RzComboBox4CloseUp(Sender: TObject);
begin
FreshPlantList(); 
end;

procedure GetPlantToolBarInfo(pPlantBase:Pointer; var stInfo:stPlantToolBarInfo);
var
nType:integer;
nMaxRecovery:integer;
nCurRecovery:integer;

begin
asm
    pushad
    mov eax, pPlantBase
    mov ecx, [eax + $34]
    mov nType, ecx

    mov ecx, [eax + $24]
    mov nCurRecovery, ecx

    mov ecx, [eax + $28]
    mov nMaxRecovery, ecx

    popad
end;

   form1.RzEdit1.Text:= IntToStr(nType);
   form1.RzEdit11.Text:= IntToStr(nCurRecovery);
   form1.RzEdit12.Text:= IntToStr(nMaxRecovery);
end;

procedure SetPlantToolBarInfo(pPlantBase:Pointer; var stInfo:stPlantToolBarInfo);
var
nType:integer;
nMaxRecovery:integer;
nCurRecovery:integer;
begin
nType:= stInfo.nType;
   nMaxRecovery:= stInfo.nMaxRecovery;
nCurRecovery:= stInfo.nCurRecovery;
asm
    pushad
    mov eax, pPlantBase
    mov ecx, nType
    mov [eax + $34], ecx

    mov ecx, nMaxRecovery
    mov [eax + $28], ecx

    mov ecx, nCurRecovery
    mov [eax + $24], ecx
    popad
end;
end;


procedure TForm1.RzComboBox2Change(Sender: TObject);
var
stInfo:stPlantToolBarInfo;
pPlantToolBarBase:pointer;
nIndex:integer;

begin
if form1.RzComboBox2.Items.Count <= 0 then
    exit;
nIndex:= form1.RzComboBox2.ItemIndex;
FreshPlantToolBarList();
pPlantToolBarBase:= Pointer(pPlantToolBarBaseArray[nIndex]);
GetPlantToolBarInfo(pPlantToolBarBase, stInfo);
end;

procedure TForm1.RzButton1Click(Sender: TObject);
var
stInfo:stPlantToolBarInfo;
nIndex:integer;
pPlantToolBarBase:Pointer;

begin
if (form1.RzComboBox2.Items.Count <= 0) then
    exit;

nIndex:= form1.RzComboBox2.ItemIndex;
FreshPlantToolBarList();
pPlantToolBarBase:= Pointer(pPlantToolBarBaseArray[nIndex]);
// ShowMessage(IntToStr(DWORD(pGoodsBase)));
stInfo.nType:= StrToInt(form1.RzEdit1.Text);
stInfo.nMaxRecovery:= StrToInt(form1.RzEdit12.Text);
stInfo.nCurRecovery:= StrToInt(form1.RzEdit11.Text);
SetPlantToolBarInfo(pPlantToolBarBase, stInfo);
end;

procedure TForm1.RzButton6Click(Sender: TObject);
var
nPlantToolBarNum:integer;

begin
asm
    pushad
    mov eax, pGameBase
    mov eax, [eax + $144]
    add eax, $24

    mov ecx, 9
    mov [eax], ecx
    popad
end
end;

procedure TForm1.RzButton5Click(Sender: TObject);
begin
asm
pushad
mov eax, pGameBase
add eax, $5560
mov [eax], 9999999
popad
end;
end;

procedure TForm1.RzComboBox3CloseUp(Sender: TObject);
begin
FreshGoodsList(); 
end;

procedure TForm1.RzComboBox2CloseUp(Sender: TObject);
begin
FreshPlantToolBarList(); 
end;

function WriteMemory(szProcName:PChar; pAddr:Pointer; szBuf:array of char; dwSize:DWORD):boolean;
var
hGameWnd:HWND;
dwID:DWORD;
hProc:THandle;
dwWriteByte:DWORD;

begin
hGameWnd:= FindWindow(nil, szProcName);
GetWindowThreadProcessId(hGameWnd, dwID);
hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, dwID);
if hProc = 0 then
    begin
    Result:= false;
    exit;
    end;

WriteProcessMemory(hProc, pAddr, @szBuf, dwSize, dwWriteByte);
CloseHandle(hProc);

Result:= true;
end;

procedure ModiryPlantToolBar();
var
nMaxPlant:integer;
i:integer;
pPlantBase:Pointer;
n, nIndex:integer;

begin
nIndex:= 0;
nMaxPlant:= GetMaxPlantNum();
for i:= 0 to nMaxPlant - 1 do
begin
    pPlantBase:= GetPlantToolbarBase(i);
    asm
      pushad
      mov eax, pPlantBase
      mov [eax + $28], 0
      popad
    end;
    nIndex:= nIndex + 1;
end;
end;

procedure TForm1.RzButton7Click(Sender: TObject);
var
szBuf:array[0..2] of char;

begin
szBuf[0]:= Char($90);
szBuf[1]:= Char($90);
szBuf[2]:= Char($90);
WriteMemory('植物大战僵尸中文版', Pointer($488f7d), szBuf, 3);
ModiryPlantToolBar();

asm
pushad
mov eax, pGameBase
add eax, $5560
mov [eax], 9999999
popad
end;
end;

procedure GrowPlant(x,y,nType:integer);
begin
asm
    pushad
    mov eax, y
    push -1
    push nType
    push x
    push pGameBase
    mov edi, $0040D120
    call edi
    popad
end;
end;
procedure TForm1.RzButton8Click(Sender: TObject);
var
x,y:integer;
nType:integer;
n:integer;

begin
randomize;
nType:= 0;
n:= 0;
for x:= 0 to 8 do
begin
    for y:= 0 to 5 do
    begin
    if RzComboBox5.ItemIndex = 0 then
      nType:= math.RandomRange(0, 48)
    else if RzComboBox5.ItemIndex = 1 then
    begin
      nType:= n;
      n:= n + 1;
      if n = 48 then
      n:= 0;
    end
    else
      nType:= RzComboBox5.ItemIndex - 2;

      GrowPlant(x, y, nType);
    end;
end;
end;

procedure TForm1.TabSheet1Show(Sender: TObject);
var
i:integer;
begin
RzComboBox5.Add('随机种植');
RzComboBox5.Add('顺序种植');

for i:= 1 to 48 do
    RzComboBox5.Add(IntToStr(i));
    
    RzComboBox5.ItemIndex:= 0;
end;

procedure TForm1.TabSheet1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
GetGameBase();
end;

procedure TForm1.RzButton9Click(Sender: TObject);
var
szBuf:array[0..3] of char;

begin
szBuf[0]:= Char($90);
szBuf[1]:= Char($90);
szBuf[2]:= Char($90);
szBuf[3]:= Char($90);

WriteMemory('植物大战僵尸中文版', Pointer($52FCF0), szBuf, 4);
end;

procedure KillAllMonster();
var
pMonBase:Integer;
n, nIndex:integer;
stInfo:stMonsterInfo;
begin
nIndex:= 0;
pMonBase:= 0;
repeat
    pMonBase:= Integer(GetMonsterBase(@pMonBase));
    if pMonBase = -1 then
    begin
      exit;
    end;
    asm
    pushad
    mov eax, pMonBase
    mov [eax + $c8], -1
    popad
    end;
until(false);
end;

procedure TForm1.RzButton10Click(Sender: TObject);
begin
ShowMessage('由于种种原因,怪物需要再K它一下,O(∩_∩)O哈哈~');
KillAllMonster();
end;

end.

以上分析中,红色的数据经过《植物大战僵尸中文第二版》测试通过。

---------------------------------------------------------------

年度版:

阳光: [[7794F8]+868]+5578

植物冷却状态地址(0为不可用,1为可用):

第1格: [[[7794F8]+868]+15C]+70

第2格: [[[7794F8]+868]+15C]+C0

第3格: [[[7794F8]+868]+15C]+110

第4格: [[[7794F8]+868]+15C]+160

第5格: [[[7794F8]+868]+15C]+1B0

第6格: [[[7794F8]+868]+15C]+200

第7格: [[[7794F8]+868]+15C]+250

第8格: [[[7794F8]+868]+15C]+2A0

第9格: [[[7794F8]+868]+15C]+2F0

第10格: [[[7794F8]+868]+15C]+340