俠盜獵車:聖安地列斯(GTA:SA)原創CLEO教程?

說明:我學習CLEO也有一段時間了。可供參考的資料少之又少,唯一的一點還都是在外國網站上找的英文資料,開著詞霸我就一點一點地看啊看。最後也就能製作一些簡單的作品,太複雜的還希望看到此文的高手給予指點。本教程是入門級別,主要是我學習的一些心得,希望能給對CLEO製作感興趣的朋友們一點幫助。

俠盜獵車:聖安地列斯(GTA:SA)原創CLEO教程

工具/原料

Sanny Builder

CLEO3

GTA:SA

引言:CLEO的環境和基本說明

《俠盜獵車:聖安地列斯》,英文名GTA:SA,是一款集第三人稱射擊、賽車競速、角色扮演、戀愛養成等元素為一體的經典遊戲,更可喜的是遊戲給各位喜愛DIY的玩家多方面的介面,大家可以從不同角度去修改遊戲使其個性化,CLEO即是基於GTA:SA的一種功能MOD,通過它可以實現很多根本不敢想的功能,比如讓遊戲主角在天上飛,海里的鯊魚會吃人,像蜘蛛俠一樣爬到牆上,發射六脈神劍等等,可以說是其樂無窮的一種MOD。

想在遊戲中使用CLEO功能,首先需要安裝CLEO環境,去CLEO的主頁下載最新的cleo3,地址: 左上角有兩個連結,第一個是自動安裝程式。下載後安裝到你的遊戲目錄下,這時開啟遊戲目錄,你會發現多了一個CLEO資料夾。以後你在網上下載的CLEO就可以放在這個資料夾下了。注意只有副檔名為.cs或NaN的檔案才能放在CLEO目錄,.fxt檔案要放在CLEO_TEXT目錄下。遊戲執行時載入所有cs檔案,玩家可以使用全部功能。

CLEO功能主檔案的副檔名是cs(CLEO Script),一些任務類CLEO還有副檔名為cm(CLEO Mission)的任務檔案,放在CLEO資料夾根目錄下;此外還可能有副檔名為fxt的檔案,是CLEO中所需要的文字描述,可以用記事本編輯,放在CLEO\CLEO_TEXT資料夾下;如果還有副檔名為txd的,放在遊戲目錄下的models\txd資料夾下。若還有其餘檔案請參考該MOD的說明。

在遊戲中使用CLEO功能,需要詳細閱讀幫助檔案,知道其功能,使用功能的方法(快捷鍵或作弊碼),使用功能所需要的條件(步行或乘車),以及一些可能導致遊戲錯誤的BUG的說明,儘量避免在這些情況下使用CLEO,這是很重要的,免得你在沒存檔之前錯誤退出而捶胸頓足。

CLEO的修改和製作需要一款軟體:SannyBuilder(簡稱SB),在其官網上可以免費下載( ),安裝完成以後就可以使用了。如果出錯需要在Tools-Options裡設定SA的安裝路徑。

SB可以開啟main.scm檔案,.cs檔案,NaN檔案以及所有的文字檔案。在開啟文字檔案的時候就是一個純粹的文字編輯器;在開啟CLEO檔案和MAIN檔案時先自動反編譯出原始碼存為txt放在當前目錄,再開啟該txt,我們做好修改以後,需要按下F7鍵,程式完成三個步驟:儲存當前文件(txt),編譯成CLEO的cs檔案或main.scm檔案,複製該檔案到遊戲目錄(如果不在原始目錄的話),cs和cm放到CLEO下,main.scm放到Script下,總之各歸各位。大概就是這麼一個流程。

這就是CLEO環境和開發環境的簡單介紹,對於CLEO製作和編輯感興趣的請繼續看下文,只對使用感興趣的就到這裡為止了。

第一課:引例◆一個簡單CLEO的橫向剖析

CLEO的學習是從修改開始的,如果一開始就講一大堆程式碼,變數,語句之類估計會嚇跑一堆人,呵呵,好了不多說了,我們開始吧。

這是一個程式碼很簡單的CLEO,曾經作為火星物品被封鎖,主檔名是repair.cs,主要功能是在車上的時候,按Y鍵可以把車修好,就不用去噴漆處了。

以下是該CLEO原始碼和我作的說明,每條語句的//後:

// This file was decompiled using SASCM.INI published by Seemann ( on 13.10.2007

{$VERSION 3.1.0027}

{$CLEO .cs}

//-------------MAIN---------------

//注意以上程式碼不可缺少,它標誌著這是一個CLEO檔案,而不是main.scm檔案

thread 'ENGINE' //引號裡的是CLEO的名稱,必須保證不會和已有的CLEO重名

:ENGINE_11 //這是標籤,為語句跳轉所設

wait 10 //等待10毫秒

if //如果,條件判斷

Player.Defined($PLAYER_CHAR) //玩家是否定義?真正含義不解,沒有這個判斷也行

jf @ENGINE_11 //如果條件不滿足的話跳轉到ENGINE_11,滿足的話繼續執行

if and //多條件必須同時滿足,表示與的關係

0449: actor $PLAYER_ACTOR in_a_car //主角是否在車裡

00E1: player 0 pressed_key 11 //是否按下了功能鍵11(遊戲預設是Y鍵)

jf @ENGINE_11

03C0: $CAR_REP = actor $PLAYER_ACTOR car //定義主角所乘車輛的控制代碼變數

0A30: repair_car $CAR_REP //修車

jump @ENGINE_11 //無條件跳轉

0A93: end_custom_thread //結束標記

大家可以在SB裡新建一文件,將上面的程式碼拷進去,就能編譯了,//是註釋標記,不受影響。

看懂了之後我來做幾點說明。SB的程式設計語言似乎沒有迴圈這麼一說,全是goto語句,這對適應了結構化程式設計的人來說是相當不習慣的。總是被程式碼拖著,一會兒跳到這裡,一會兒跳到那裡。但是對於遊戲來說,的確很需要這種跳轉,這樣使得程式碼更容易被遊戲所理解。

進入遊戲後,首先判斷玩家是否載入正常,不是的話重新執行,直到載入正常,然後判斷玩家是否在車裡並按了Y鍵,如不是重新執行,直到滿足條件為止,設定車的控制代碼變數,然後用該變數就能控制玩家所乘坐的車了。本程式碼的目的是修車,就只有一句程式碼,所以說0A30: repair_car $CAR_REP才是這段程式碼中最重要的一句。

我們可以在這個CLEO的基礎上,增加自己想有的功能,比如說覺得無償修車太沒意思了,可以在修車的同時減少玩家的金錢數:

Player.Money($PLAYER_CHAR) += -10000 //本句加在修車句之後

呵呵,這就可以了,加太多語句就跑題了。好了,本次課就到這裡了,如果覺得還行的話歡迎下次再來哦,下一次就開始講解SB的語法了,畢竟搞程式設計不懂語法不行啊 ^_^

第二課:opcode規則和一般語法

在上一個例子中不知大家有沒有注意到一些程式碼前面有類似0A93:的字樣,這就是所謂的opcode,每一個opcode都有一個特定的含義,目前官方似乎不願意公佈所有opcode的詳細用法,這就給我們製作CLEO的製造了麻煩,我們不得不通過分析一些CLEO來研究每一條opcode的用法。一般情況下,如果你知道了一種功能的opcode,你就可以在CLEO中實現這種功能,比如修車的0A30:,只有知道這條opcode的人才會用它來編出有修車功能的CLEO。

Opcode並不一定每條語句都得有,一些簡單的語句可以省略opcode,如果你編譯的時候出現了錯誤,可能是你把不該省略的opcode給省略了,所以建議大家除了那些有例子可以省略的語句外,一律加上其opcode。

在SB介面下,你把游標定位到某一條語句時,狀態列就會顯示該語句的opcode用法,比如03C0: $CAR_REP = actor $PLAYER_ACTOR car,顯示的是03C0: expecting 2 params,意思是這個opcode有兩個變數,表現出來就是$CAR_REP和$PLAYER_ACTOR。

好了,下面就是SB的語法介紹了。

SB語句不區分大小寫。

變數:SB的變數命名規則和別的語言大不相同,大致分為兩類,功能是一樣的,具體喜好就看程式設計師自己了。它們是以$開頭的字串和以@結束的數字。舉例:$sanny,[email protected]

變數支援隱式定義,即直接使用,但全域性變數需要定義。

變數的型別包括常用的整型,浮點型以外,還有控制代碼型,即上例中標誌玩家所乘車輛的變數。

語法:算術運算和比較運算同C語言的語法,賦值語句支援+=等方法。

基本語法是條件判斷和跳轉。其他語句還真不怎麼熟悉,用的很少。

跳轉:jump @MAIN_4,提前保證有:MAIN_4的標籤,以便於跳轉時找到目標

單一條件判斷並跳轉:

If

語句,返回值必須為真或假,從英文字面上看是肯定語氣的opcode

jump_if_false @MAIN_4 如果條件不成立,則跳轉到指定語句

本句可簡寫為 jf @MAIN_4,意思一樣

多條件判斷並跳轉:

If and

語句1

語句2

…… 必須同時滿足所有語句才行

jf @MAIN_4

If or

語句1

語句2

…… 只需滿足其中一條語句就行

jf @MAIN_4

可以說SB的基本語法也就這麼多,沒什麼難的。主要的難點在於靈活運用每一條opcode,每一條opcode都有它的引數表、固定格式和功能用法,是不能亂用的,比如01B6: set_weather 1是設定天氣的opcode,如果斷章取義寫成了01B6: repair_car $CAR,那就是嚴重的錯誤了,所以務必要弄清楚opcode的格式規範。在SB介面下按Ctrl+Alt+2可以開啟一個opcode查詢器,能查到所有opcode的基本用法,但也只能到這個程度,更復雜的使用和技巧就只有靠我們自己去摸索和發現了。

好了,這一課就到這裡了,以後的教程我會結合各種各樣不同型別的CLEO程式碼進行分析,讓大家在不同的功能中豐富和探索CLEO的知識。

第三課:CLEO與玩家的介面

當編好了一個很經典的CLEO時,必須設定與玩家的介面,即觸發條件。沒有介面,CLEO就像是程式設計中未呼叫的函式,失去了它本身的意義。

CLEO與玩家的介面表現在三個方面:1、自動觸發;2、玩家就像輸入作弊碼那樣觸發;3、玩家在鍵盤上按下某個鍵時觸發。自動觸發的CLEO很多,比如汽車耐久度計量槽,汽車加油,NPC跳樓等等。然而我們用的最多的,還是那些經典的,可以觸發的功能CLEO。

大家從網上下載的CLEO,很多都存在快捷鍵衝突的問題,像上例修車那樣,用功能鍵Y定義,實在是太不合理了。還有那個呼叫出租的,居然設成了1和2。所以我們這一課的主要目的,就是把這些不合理的快捷鍵改掉,讓每個CLEO互相都不起衝突。

CLEO的快捷鍵分為兩類,按鍵,功能鍵和作弊碼,下面分別說明

①按鍵類,即按下1等單鍵,或Ctrl+W等組合鍵實現介面功能

核心程式碼:0AB0: key_pressed 0x73

0AB0是opcode,不可缺少,0x73是一個變數,型別為KeyCode碼,比如我設定快捷鍵為U,程式碼應該寫成:0AB0: key_pressed 85。

如果想實現Ctrl+T,if語句的完整程式碼如下:

if and

0AB0: key_pressed 17 //Ctrl的KeyCode是17

0AB0: key_pressed 84

jf @MAIN_1

這樣,就能輕易實現按鍵類快捷鍵的設定了。大家可以依葫蘆畫瓢,將那些不合理的或衝突的快捷鍵統統改掉,這下所有CLEO都能共用啦!

字母和數字的KeyCode碼同ASCII碼,其他特殊字元的KeyCode列舉如下:

俠盜獵車:聖安地列斯(GTA:SA)原創CLEO教程

②功能鍵類

核心程式碼:00E1: player 0 pressed_key 19

之所以叫功能鍵,就是遊戲中按下會起到一定效果的鍵,比如上下左右,開火或蹲下等,在遊戲的設定中可以調,但無論調到那個鍵,CLEO中設定的功能鍵都會隨之改變,沒有按鍵的單一固定特性。設定此類功能鍵時應特別注意衝突問題,最好加上and和按鍵類一起使用。

修車CLEO的觸發鍵是Y,這就是設定的功能鍵。如果你想設定成Ctrl+蹲下的快捷鍵,可以用if and來實現,程式碼為

if and

0AB0: key_pressed 17

00E1: player 0 pressed_key 20

jf @MAIN_1

以下列舉常用的功能鍵及其程式碼:

2 left/right

3 steer back/up

4 special ctrl left/right

5 special ctrl up/down

6 secondary fire

7 look left

8 hand brake

9 look right

10 next radio station

11 previous radio station

12 no

13 yes

15 camera

16 brake/reverse

17 enter/exit

18 accelerate

19 fire

20 horn(in car)

21 submission

22 walk(on foot)

23 RMB vehicle mouse look

可能有一些不準,具體的大家可以自己進行測試。

功能鍵的設定適合製作一些武器類的CLEO,但大多數情況下並不推薦使用。

③作弊碼類

作弊碼的設定比較難,需要記憶體編輯的基礎,初學者完全可以略過,以下也是我的一些心得,僅供參考。

1、eject.cs的作弊碼(4字元作弊碼)

核心程式碼:

0A8D: [email protected] = read_memory 9867536 size 4 virtual_protect 0

if

04A4: [email protected] == 1162495316 // @ == any

jf @EJECT_11

分析:從969110/16開始(開區間)讀取4個單位長度(只能是4個),這是使用者連續輸入4個鍵的儲存位置

1162495316/10=454A4554/16,拆開來就是45、4A、45、54,再轉換成10進位制並查出對應的ASCII字元即為密碼“EJET”

操作:要修改這個CLEO的作弊碼,可以按照我的步驟進行。假如修改成“ABCD”(只能是4個字元),先查出每個字元的ASCII碼並分別轉換成16進位制,得到41、42、43、44,連起來,為41424344,轉換為10進位制,得到1094861636,這就是你在記憶體中想要讀到的值。然後就可以寫程式碼了,將上面程式碼的判斷語句改成04A4: [email protected] == 1094861636即可。

2、firework.cs的作弊碼(4x字元作弊碼)

核心程式碼:

[email protected] = -229907

if

&0([email protected],1i) == 1179210309

jf @FW_11

[email protected] = -229908

if

&0([email protected],1i) == 1464816203

jf @FW_11

&0([email protected],1i) = 1464816128

分析:-229907應該也是記憶體地址,一個地址儲存使用者輸入的4個連續鍵。讀入使用者第一次輸入4個鍵,1179210309/10=46495245/16,拆開來就是46、49、52、45,即為“FIRE”

然後讀入下一個記憶體地址的資料,1464816203/10=574F524B/16,拆開來就是57、4F、52、4B,即為“WORK”,連起來就是密碼“FIREWORK”,最後的一句是記憶體的改寫,避免程式重讀錯誤。

操作:除了格式,基本原理和EJET一樣,大家先把作弊碼在記憶體的對應值算好,再帶入“&0([email protected],1i) ==*”比較語句即可,如果是12字元作弊碼,在加一個判斷語句即可,注意[email protected]的變化規律。大家只需照套路走就是了,&0([email protected],1i)的用法我還不是很懂。

3、amrifle.cs的作弊碼(4字元以下作弊碼)

核心程式碼:

0A8D: [email protected] = read_memory 9867535 size 4 virtual_protect 0

if

[email protected] == 1095586304

jf @AMR_11

0A8C: write_memory 9867536 size 4 value 1095586304 virtual_protect 0

分析:和4字元類似,1095586304/10=414D5200/16,即為“AMR”,但是注意讀取的開始記憶體地址,4字元是9867536,3字元是9867535。最後一句也是記憶體改寫以避免程式重讀錯誤。

4、laevateinn.cs(任意字元作弊碼)

核心程式碼:

[email protected] = -229906

008B: [email protected] = &0([email protected],1i) // (int)

0085: [email protected] = [email protected] // (int)

[email protected] /= 65536

[email protected] *= 65536

0062: [email protected] -= [email protected] // (int)

if

[email protected] == 19521 //LE

jf @LVTN_11

[email protected] = -229907

if

&0([email protected],1i) == 1163280724

jf @LVTN_11

[email protected] = -229908

if

&0([email protected],1i) == 1162432078

jf @LVTN_11

&0([email protected],1i) = 1162432000

分析:這段程式碼比較長,目的是在記憶體中獲取“LAEVATEINN”,10個字元作弊碼,可以切割來看,從右到左4位一組,LA,EVAT,EINN,算出來就是19521,1163280724,1162432078。後八位和2例類似,只是前兩位的程式碼比較難懂。大家可以注意觀察下記憶體的取得地址和前例的不同之處,以便觸類旁通

5、hud.cs(4例的三字元補充)

核心程式碼:

[email protected] = -229908

008B: [email protected] = &0([email protected],1i) // (int)

0085: [email protected] = [email protected] // (int)

[email protected] /= 16777216

[email protected] *= 16777216

0062: [email protected] -= [email protected] // (int)

if

[email protected] == 4740420 //485544

jf @HUD_28

&0([email protected],1i) = 1213547520

分析:作為4例的補充,本程式碼的目的是“HUD”,三字元的演算法和兩字元略有不同,主要是在[email protected] /= 16777216上面,大家可以試試把這段字元轉換成16進位制,即為1000000,而65536則是10000,多了兩個16進位制字元位,正好就能區分4位和3位密碼了。大家可以觸類旁通,試試2位的該怎麼寫。

6、PEDSpawn.cs(傻瓜的作弊碼設定,適合所有人)

核心程式碼:

if

0AB0: key_pressed 80

jf @PEDS_113

[email protected] = 1

[email protected] = 0

:PEDS_113

if and

[email protected] == 1

0AB0: key_pressed 69

jf @PEDS_149

[email protected] = 2

[email protected] = 0

:PEDS_149

if and

[email protected] == 2

0AB0: key_pressed 68

jf @PEDS_185

[email protected] = 0

jump @PEDS_218

分析:我想不用我多說了吧,值得注意的是單純地照著這個思路下去會有一點問題,三個字元的觸發判斷必須要聯絡在一起,本例中[email protected][email protected]變數就是聯絡在一起的紐帶。大家注意觀察觀察就不難發現,如果沒有這條紐帶的聯絡,就無法實現作弊碼的效果了。

這個例子程式碼雖然含金量不高,但通俗易懂適合所有人使用,大家只需以此類推就能寫出任意個字元的作弊碼,但用太多判斷語句,執行效率不高,多了的話會有讓人無法忍受的延遲。

這一課說了這麼多,總而言之就是如何設定快捷鍵來觸發CLEO,想當初我就是為了這個目的來學習CLEO的,呵呵,當時沒有人會的東西被我研究出來了,我相當有成就感。遺憾的是並不是每一條程式碼都理解的十分透徹,可惡的SB並不給出詳盡的解釋,我想研究CLEO的路應該還很長,很長……

程式碼, 俠盜, 列斯, 聖安,
相關問題答案