PVZ一代修改教程:戴夫的話(huà)的修改相關(guān)
特別聲明:本教程所說(shuō)的PVZ僅指英文原版、漢化一以及漢化二及這三個(gè)版本的改版
閱讀此教程前請(qǐng)確保以及會(huì)一些基礎(chǔ)的修改及匯編
關(guān)于戴夫的話(huà),研究最遲在2020年五月就完成了,具體的日期我記不清了。
當(dāng)然,這里的教程不包括如何新增一個(gè)戴夫的動(dòng)作,那不屬于“戴夫的話(huà)”

如何修改原版戴夫的對(duì)話(huà)
在原版的pak中,properties文件夾里的LawnStrings.txt文件中,有若干結(jié)構(gòu)為[CRAZY_DAVE_%d[1]]的片段。
下面摘抄一段英文原版的資料:
[CRAZY_DAVE_201]
Evening, {PLAYER_NAME}.
[CRAZY_DAVE_202]
Those zombies just won't let up, will they?
……
[CRAZY_DAVE_302]
You know what that means...
[CRAZY_DAVE_303]
Crazy Dave's Twiddydinkies is open for business! {MOUTH_SMALL_SMILE}
這下面就是對(duì)應(yīng)的文本。
而其中比較特殊的文本段,例如{PLAYER_NAME}和{MOUTH_SMALL_SMILE}
這兩段將會(huì)在后面進(jìn)行說(shuō)明。
在這里,來(lái)說(shuō)明一下原版怎么確定戴夫的對(duì)話(huà)是怎么結(jié)束的。
首先,原版的代碼會(huì)從一個(gè)特定的編號(hào)開(kāi)始(可以結(jié)合后面的代碼內(nèi)容查看),然后從那里開(kāi)始進(jìn)行對(duì)話(huà),例如從201開(kāi)始,然后依次播放202、203、204等。
播放到207后,由于208編號(hào)沒(méi)有對(duì)應(yīng)的文本,所以戴夫就停止對(duì)話(huà)了。
簡(jiǎn)而言之,在修改pak的時(shí)候,如果增添一個(gè)208,就可以在207后面再添加一個(gè)對(duì)話(huà)了。
同樣,后面在新增的時(shí)候,也要確定這一點(diǎn),不要讓他們連接起來(lái)[2]

特殊文本句段
我暫且把特殊文本句段分成兩類(lèi),變量類(lèi)句段和控制類(lèi)句段[3]
變量類(lèi)句段是指,他的內(nèi)容實(shí)際上不會(huì)是你輸入的內(nèi)容,他會(huì)被一些特定內(nèi)容給替換掉。
共有以下幾種:
{PLAYER_NAME}
{MONEY}
{UPGRADE_COST}
{SELL_PRICE}
{PLANT_TYPE}
包括了:稱(chēng)呼玩家的名字、金錢(qián)、升級(jí)費(fèi)用、花園里賣(mài)植物使用的價(jià)格和植物類(lèi)型
由于這些句段命名過(guò)于直接,我就不詳細(xì)說(shuō)明了。
關(guān)于他們的代碼實(shí)現(xiàn)原理,我會(huì)在后面進(jìn)行論述。
控制類(lèi)句段是指,他的內(nèi)容會(huì)指定戴夫當(dāng)前的動(dòng)作是什么[4],在原版中,有以下幾種:
{MOUTH_SMALL_SMILE}
{MOUTH_BIG_SMILE}
{SCREAM}
{SCREAM2}
{NO_SOUND}
{NO_CLICK}
{MOUTH_SMALL_OH}
{DELAY_%d}
{SHOW_WALLNUT}
{SHAKE}
{SHOW_TREE_FOOD}
臨時(shí)收集,可能不全。
這些句段命名也過(guò)于直接,我也不詳細(xì)說(shuō)明了。
關(guān)于他們的代碼實(shí)現(xiàn)原理,我會(huì)在后面進(jìn)行論述。

添加關(guān)卡開(kāi)頭的戴夫?qū)υ?huà)
大概在0x0043AB96左右,有一連串的檢測(cè)關(guān)卡,然后改寫(xiě)ebp+0x28的值
我們通過(guò)觀察可以發(fā)現(xiàn),ebp+0x28的值就是起始對(duì)話(huà)編號(hào)(上文的特定的編號(hào)),當(dāng)檢測(cè)到規(guī)定關(guān)卡時(shí),運(yùn)行這串代碼。
所以,只用在這段加入檢測(cè)其他關(guān)卡,然后改寫(xiě)ebp+0x28到自己在文本LawnStrings.txt文件中添加的新文本的編號(hào),然后就完成了。
關(guān)于這段的實(shí)際原理請(qǐng)自行摸索,或參考下一節(jié)(在游戲中途叫出戴夫)進(jìn)行分析

在游戲中途叫出戴夫
原版的一周目4-5,砸罐子中途,戴夫多次出現(xiàn)了。
這意味著,戴夫不僅可以在關(guān)卡開(kāi)頭出現(xiàn),在關(guān)卡中途也可以出現(xiàn)[5]。
所以我們也可以在關(guān)卡中途調(diào)用戴夫。
由于我很久沒(méi)用早忘了,也為了防止科技泛濫,這里我只提供我當(dāng)初找到的思路:
①開(kāi)一局一周目4-5
②找到波數(shù)指針([[[[6a9ec0]+768]+160]+60]或[[[[6a9ec0]+768]+160]+6C],依舊是記不清了[6])
③由于第一波、第二波、第三波的對(duì)話(huà)不一樣,查找該指針的訪問(wèn),可以輕易的找到我們需要的地址
請(qǐng)自行摸索

特殊句段的實(shí)現(xiàn)原理
使用OD可以發(fā)現(xiàn),在0x00453E10往下很長(zhǎng)一段,都有這些特殊句段的相關(guān)信息。
變量類(lèi)句段原理->搜索到指定句段->替換該句段到指定的文本
替換句段時(shí)大量運(yùn)用了幾個(gè)函數(shù)
0x00513660 String_ReplaceSubString
0x00403E20?String_SetSubstring
具體原理依舊自己研究
控制類(lèi)句段則大量運(yùn)用了
0x004419A0 String_FindSubString_CharsNum
找到指定文本后,進(jìn)行對(duì)應(yīng)的操作。
而在實(shí)際顯示文本時(shí),會(huì)刪去控制類(lèi)句段[7]

關(guān)于Upsell的戴夫
Upsell的戴夫比較特殊,他不是點(diǎn)擊進(jìn)入下一句,而是依靠延遲實(shí)現(xiàn)[8]的。
具體研究方法類(lèi)似上面,先找到3300(Upsell的開(kāi)始段),然后查訪問(wèn)啥的。

結(jié)語(yǔ)
該教程不建議死搬硬套,建議理解后食用
教程寫(xiě)的不夠親民是因?yàn)椴幌胱尶萍继簽E,擁有一定的PVZ修改經(jīng)驗(yàn)和編程知識(shí)是能看懂的。
由于戴夫可以讓很多改版更好的介紹特性,我就把這個(gè)東西做成教程了
該文章寫(xiě)的比較匆忙,后面可能會(huì)進(jìn)行一些修改

參考資料與文獻(xiàn)
PVZ指針表
Hope_20121221_(貼吧名)等人于2011年、zjfaok(貼吧名)等人于2014年研究發(fā)布
崇明人家123(貼吧名)于2017、2018年收集整合
Dr丶小黑、康師傅豆腐、4573去、Ghastasaucey、六三enjoy(均為貼吧名)先后于2019到2021增添修補(bǔ)
PVZ函數(shù)表
失控的指令(貼吧名)于2020、2021年收集整理
諸位的研究
主要是Ghastasaucey、4573去在2020年進(jìn)行的研究

注釋
[1] %d見(jiàn)C語(yǔ)言,指的是十進(jìn)制有符號(hào)整數(shù),下文的{DELAY_%d}同理
[2] 原版的對(duì)話(huà)大多都隔著100及以上的間隔,所以一般不會(huì)連起來(lái)
[3] 這兩個(gè)名詞是自己命的,不要認(rèn)為是專(zhuān)業(yè)的名詞
[4] 其中{DELAY_%d}指定的不是動(dòng)作
[5] 花園里也有類(lèi)似的例子出現(xiàn)
[6]?顏色僅為方便辨認(rèn)指針
[7] 刪去的時(shí)機(jī)需要驗(yàn)證
[8]?{DELAY_%d}

文章作者:Ghastasaucey