(十五)科技全開——前方高能,BOOM
其實這一小節,最晚應該在第四篇的十小節來講述的,這樣是按照一條線索來講的,容易理解和把握筆者修改時的思路,以一點逐漸擴大。由於筆者的一些原因(一是牽涉到的數據結構比較多——3個,筆者當時沒有完全理解;二是當時筆者發現一個關鍵位置——代碼很復雜,並且紅警全能王也進行了復雜的修改。因於此,筆者當時沒深入就轉而去搞其他的了),當筆者想寫科技全開的時候,卻發現講不通,又不想只給出一個這么改就行的模糊回答,因為這是百科!結果就是,第十小節生硬地變成了打開小地圖雷達——————
有些東西終究是逃不掉的,Let’s face it.對第八節——添加任意建造項,是否還有印象?可以回過去再看看第三篇,傳送門。其中,我提到是這樣確定類型編號的:當你展開基地車的時候,會獲得建造發電站的選項;建造完發電站,獲得礦場和兵營的選項………如果讀者親自實驗過,就會知道每次刷新建造項都會頻繁調用那個函數添加建造選項。那么誰調用了這里,調用者將會判斷決定添加什么選項。於是在函數頭下斷點,返回上一層,我們來到:
分析這里能得到一些東西:循環次數——所有建築物種類數目(A35CE8,即game.exe+635CE8),(建築物)建造描述對象數組(A35CDC)。還有輕易就知道CALL<添加建造選項>前面的CALL就是得到某種建築是不是應該被添加的的判斷函數。
並且004E3660被很多地方調用,然而這個函數有很多判斷和很多出口,修改並不是很容易。一旦做了努力,修改成功,科技全開將是顯而易見的。例如紅警全能王就是修改了這里:
這個函數被重新跳轉到2931F96的一個自定義函數。注意:這個地址是臨時申請的,每次都會變的。同樣也是一個挺復雜的自定義函數,其中還調用了其他自定義函數。此處只是為了給出直接修改這個函數實現科技全開的思路並舉例證明可行,並無意侵犯原作者權利。由於紅警全能王版本及修改版繁多,歷史久遠(最初貌似是聯網獲取核心DLL的,后來被大神做出本地驗證的單機版,最近我下載的是紅警全能王谷子貓綠色珍藏版),我也搞不清誰是原作者,在未獲得許可的情況下,還是不公開具體實現。有興趣的可以自行下載分析,我也好偷懶
由上面,已經給出科技全開的一種實現原理和思路了。本可以由此打發讀者,棄坑的,但是我騙不了自己,還有自己同樣在講的優雅。好復雜的原函數,好復雜的自定義函數,能不能簡單點……我很懶的,不想自己搞。於是找到了紅色警戒2修改大師,附近的Case 7(建築物)被簡單的修改成如下(已由作者林毛口頭授權公開):
其他的Case28,Case10,Case3也是類似的。+55C偏移是什么鬼?為什么要和-1比較?為什么要這么改?為了給讀者有個解釋,我終於下決心去看原函數了。最初我大體一看也是被這么長的函數嚇壞了,還那么多判斷,就果斷繞道去看別人怎么實現的了……結果現在才發現開頭不遠就有:
紅警修改大師的作者看來是認真分析過的,我站在他人的肩膀上~~之所以上面+55C偏移我確定是科技需求等級,是有原因的。記不清在哪里看到的,修改紅警ini配置文件來啟用隱藏兵種,修改的就是科技需求值-1,再通過對比其他兵種就基本確定了。破解、修改、入侵都一樣,要思路開闊,方法靈活~
最初,我以為這樣就可以優雅的科技全開了。然而今天我想整理這篇文章時才發現我錯了,直接調用添加建造選項的CALL能添加成功,我修改成這樣為什么不能成功,紅警修改大師為什么修改有效?原因,下節分析……這里先重新完善一個內存結構/游戲對象,提出與此相關的幾個新對象。昨天不想寫博文,為了拖延去看了看我當時由於找到另一個建造CD指針就沒仔細分析的,結果解決了今天我遇到的問題——努力就有收獲,不死方能最強王者(但是我對LOL心已經死了,反射弧太長)。
//對應游戲界面中的建築選項 //游戲中有4個ConstrctionOptions數組,對應4個建造選項卡 //是struct,不是class。結構數組在內存上是連續的,而對象數組存儲的是對象指針 //所以上一個數組元素地址加上元素大小得到下一個數組元素地址 struct ConstructionOption { int nCount; //+0,建造選項數目,僅在第一個建造選項中有意義 int nID; //+4,建造編號 int nType; //+8,建造類型,07標識建築(基礎建築、防御建築) int nUnkonwn; //+C,未知標識數,基礎建築和防御建築此值不同 ConstructionProgress* pConProgress; //+10,指針指向建造進度對象 //...其他未知數據 //size=0x30,這也是為什么第一篇中各CD基址相差0x30的原因 //很明確的告訴你,該結構沒有指針指向ConstructionDescriptor //對應的圖像、名稱等等在ConstructionDescriptor中,因此我起的名字還是相當合理的 //那游戲怎么將Option和Descriptor聯系起來的?請繼續閱讀下一篇 } //對應建造的過程 class ConstructionProgress { //... int nCD; //+24,當前單位建造CD int nTotalTime; //+28,全局建造時間,聯網對戰中可能根據此同步建造 int nNum; //+4C,此次建造的剩余隊列數量,單獨修改此值會崩潰 // 猜想與總建造隊列數值不一致引起 int nNeededMoney; //+5C,還需求多少金錢此單位建造完成 //... } //對應游戲中的單位定義 class ConstructionDescriptor : public BaseA, ... { //以下成員繼承於基類BaseA,游戲內建築對象、作戰單位都繼承了BaseA //包括我發現的游戲內觸發器對象,標簽對象等 //BaseA或許叫做CommonObj更合適,游戲內大部分對象均繼承此類 //上面的ConstructionProgress不繼承BaseA int nGobalID; //+10,全局對象ID Char szName[16]; //+3D,單位定義名稱,修改過ini文件的應該熟悉 //... int nCost; //+550,造價 int nSold; //+554,出售價(復制中心回收) int nRequiredTechnology; //+55C,需求科技等級 //... }
我現在在想這一篇的長度是不是夠了呢?停下吧,去修改之前的錯誤,我發現第一篇描述有錯誤(那些CD基址不是對應建築或者兵種的,是相對所在格子的),也歸功於今天的遇到的問題帶來的一些重新思考。其實筆者,一直在修修改改之前的文章……從來沒寫過這么大型的百科,之前也沒寫過博文。
==========
。。。錯誤改完了,在最后補充一下第一篇承諾的詳細解釋:
以第一格CD為例。第一格CD地址:[game.exe+433A80]+24,當時在第一篇被錯誤的稱作盟軍電廠CD地址。第一篇中為了不一上來引入復雜的數據結構,簡單的讓讀者認為,game.exe+433A80存放的指針指向一個SomethingAboutConstuction結構。現在相關類/結構已經在上述完整的描述了,是時候糾正了。
game.exe+433A80存放的指針指向的是ConstructionProgress對象,game.exe+433A80這個地址是ConstructionOption結構的成員變量pConProgress,減去偏移0x10=game.exe+433A70,即第一格的ConstructionOption對象的起始地址。上面提到nCount僅在第一個建造選項中有意義,即數組ConstructionOptions[0].nCount記錄了游戲中該建造選項卡下有幾個建造選項,ConstructionOptions[1,2,3,…].nCount=0。
To be continued…
轉載請注明來源,http://www.cnblogs.com/viewll/p/4775482.html