佳礼资讯网

 找回密码
 注册

ADVERTISEMENT

楼主: xtricky

完整dato地图编辑(点击目录第一页)期待升精

[复制链接]
发表于 23-12-2006 01:44 PM | 显示全部楼层
原帖由 xtricky 于 23-12-2006 02:25 AM 发表

所以我说我在你帖里学到很多东西,姜还是老的辣。还希望你多多参与,给点意见与帮忙,因为我知道得真得太少了,有时候真的不知道要如何帮忙网友的疑问,真是《心有力而力不足》。无奈!


你太過獎了
其實還有很多人強過我
只是他們靜靜扮不懂而已

原帖由 xtricky 于 23-12-2006 02:25 AM 发表

们好厉害哦 ,我之前还在努力研究但好像还没有什么进步,一看的一头雾水。


呵呵~
我只是知道jass craft這個program而已
並不懂它到底是怎樣寫的
我一看到jass code就想睡了
回复

使用道具 举报


ADVERTISEMENT

发表于 23-12-2006 01:49 PM | 显示全部楼层
原帖由 SoNiCHaos 于 22-12-2006 11:13 PM 发表
原谅小弟的无知什么是jass code?可以快快分享一下吗??


What is JASS?
一個很不錯的講解和其他相關連接
回复

使用道具 举报

发表于 23-12-2006 01:50 PM | 显示全部楼层
原帖由 deagle-lim 于 23-12-2006 01:41 PM 发表


拍謝
剛發現到寫錯了
應該是jass craft這個城市才對

jass craft這個城市
原帖由 deagle-lim 于 23-12-2006 01:44 PM 发表

呵呵~
我只是知道jass craft這個program而已
並不懂它到底是怎樣寫的
我一看到jass code就想睡了

等下去研究研究。

[ 本帖最后由 MoNeyHearts 于 23-12-2006 01:51 PM 编辑 ]
回复

使用道具 举报

发表于 23-12-2006 01:52 PM | 显示全部楼层
原帖由 MoNeyHearts 于 23-12-2006 01:50 PM 发表

jass craft這個城市


炸到!
又謝錯字

jass craft這個程式才對!
回复

使用道具 举报

发表于 23-12-2006 02:01 PM | 显示全部楼层
war3map.j
以上就是DotA Allstars v5.84c BugFixed用Jass code寫出來的trigger
下載后用notepad打開
大家可以看看jass code到底是什麽咚咚來的

之前guinsoo也是用world edit來寫dota的
過後由於trigger越寫越多了
搞到地圖越玩越lag
loading也要半天
所以他才將gui convert去jass咯
而且jass可以讓他寫更多高級的skill

如果大家想知道ice frog怎樣寫6代的dota
可以用winmpq來開6代的dota
extract war3map.j就可以了
但是事先要import listfile進去
不然你看到的只有奇奇怪怪的名字而已
這是ice故意破壞的
就是爲了避免某人偷取dota咯

至於要去哪裏找listfile呢
在某個著名的mh網站就有了
那邊也教導破解6代dota的方法


[ 本帖最后由 deagle-lim 于 23-12-2006 02:07 PM 编辑 ]
回复

使用道具 举报

发表于 23-12-2006 02:07 PM | 显示全部楼层
原帖由 deagle-lim 于 23-12-2006 02:01 PM 发表
war3map.j
以上就是DotA Allstars v5.84c BugFixed用Jass code寫出來的trigger
下載后用notepad打開
大家可以看看jass code到底是什麽咚咚來的

之前guinsoo也是用world edit來寫dota的
過後由於trigger越 ...

意思是JassCode不会影响游戏速度咯?


开来看了,不知什么字代表什么。
回复

使用道具 举报

Follow Us
发表于 23-12-2006 02:11 PM | 显示全部楼层
原帖由 MoNeyHearts 于 23-12-2006 02:07 PM 发表

意思是JassCode不会影响游戏速度咯?


开来看了,不知什么字代表什么。


不是
而是減少它的lagness而已
畢竟有些電腦受不起dota醬勁的skill
就好像某hero可以在沒醬lag的情況下cast出完美的multiskill
如果用gui寫出來
也許有些電腦會lag下lag下的
但最重要的還是可以寫出advanced的skill
回复

使用道具 举报

发表于 23-12-2006 08:30 PM | 显示全部楼层
其实worldedit也可以写出复杂的skill分别是
jass用简单的方法弄出复杂的skill
而world edit要用复杂的方法弄出复杂的skill
回复

使用道具 举报


ADVERTISEMENT

发表于 28-12-2006 03:03 AM | 显示全部楼层
我覺得如果樓主寫關於如何寫技能的帖會更吸引我= =
回复

使用道具 举报

发表于 6-1-2007 08:48 PM | 显示全部楼层
原帖由 I3aI3yCat 于 28-12-2006 03:03 发表
我覺得如果樓主寫關於如何寫技能的帖會更吸引我= =


如我所知,dota 5.多数是‘当某个技能出现时’,就会‘triggen effect',然后就‘出现什么不一样的技能’或‘计算性的效果’。本来一支会用starcraft map edit 一到wc3就被她的超复杂程度让我...

O.O

要弄一个wc3里没有的的新技能效果就要我的命了。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 06:45 PM | 显示全部楼层
AI編輯器(AI Editor) AI編輯器是讓你創造AI(人工智慧),可以用來創造AI,進而控制軍隊的生產和攻擊策略。
 
[url=]一般(General)[/url]
名稱 - 你可以在這邊為你的AI命名。
種族 - 選擇你想要用來創造AI的種族。自定種族的選項,可以讓你整合特定的的部隊、能力和昇級。記得把自定資料匯入。


選項(Options)
設定玩者名稱 - 打開這個選項,可以設定遊戲中的玩者名稱,並輸入AI名稱。

正規戰 - 在一場標準的正規戰遊戲中,使用一個正規戰的AI。正規戰AI傾向於和同盟一起攻擊並防禦。

鎖定英雄 - 在打開這個選項之後,AI會在一場戰鬥中,將攻擊英雄列為較優先的事項。

修復建築 - 打開這個選項之後,可以在需要的時候,命令工人自動修理建築物。

英雄逃跑 - 打開這個選項之後,英雄會在他們受到重傷,或是無法攻擊時試圖逃亡。

部隊逃跑 - 打開這個選項之後,非英雄的部隊會在受到重傷,或是無法攻擊時試圖逃亡。

群組逃跑 - 打開這個選項之後,攻擊群組會在戰鬥呈現敗像或是潰敗時試圖逃亡。

毫不留情 - 打開這個選項之後,AI會找尋在敵人弱勢或是戰況不利的缺口。這個攻擊是以「敵人 - 主要突擊」為最優先。

忽略傷兵 - 打開這個選項之後,在編組攻擊隊伍時生命點數低於50%的部隊,就不會納入編組中。

移開傷兵 - 打開這個選項之後可以暫時讓受傷的部隊回家(或在附近的生命之泉)治療。

拾取物品 - 打開這個選項之後英雄會試著拿取任何路上的有用物品。

緩慢採收 - 打開這個選項之後,每次採收時只會採收到一個單位。這會讓AI在經濟方面陷入僵局。

容許變更基地 - 這個選項可以容許AI在戰局中,選擇一個新地點做為基地,來收集資源並做為撤兵的據點。

聰明砲隊 - 打開這個選項之後,砲兵部隊會在時機正確的時候,試著上前並進行攻城攻擊。

自定資料(Custom Data)

匯入 - 匯入由物件編輯器所產生的資料,來強化你的AI。

匯出 - 匯出自定資料,在物件編輯器中查看其他人自行設定的AI資料。

清除 - 從你的AI中移除所有自定資料。



條件(Conditions) -條件可以在這邊設定,做法類似觸發編輯器中的條件,但是這邊的設定只能作用在AI編輯器中。創造出來的條件可以在AI編輯器中運用。
一個很有用的概念在於,在你創造AI條件是作用在AI隊長的身上,分別有攻擊和防禦二種。這些隊長相當於隱形的部隊,為AI的領導者。攻擊隊長待在基本建築中(城鎮大堂),靜候攻擊隊伍編組完畢。一旦編隊完成之後,攻擊隊長就帶著部隊出征,然後再回到基地。防禦隊長待在基地與金礦之間,除非基地出事 - 這時防禦隊長就會帶著防禦部隊抵抗外敵。
 
[url=]英雄(Heroes)[/url]

使用的英雄 - 選擇你要Heroes Used - Choose the Heroes you want the AI為你進行訓練的英雄。可用的英雄視你所選擇的種族而定。

訓練順序 - 變更AI的訓練順序,訓練的順序視你使用的英雄而定。

技能選擇 - 變更AI控制英雄要學習什麼樣的技能。

  
[url=]建設(Building)[/url]

基本建築 - 在AI要興建建築物時,選擇你要使用的是什麼部隊。在這邊所提供的選擇項目,視你在「一般」標籤中所設定的種族而定。

礦產建築 - 在AI要興建採礦用的建築物時,選擇你要使用的是什麼部隊。一般而言這是用在不死族,不過你也可以選擇其他具有「腐土金礦開採」能力的部隊。

建造優先權 - AI在建造、研發與昇級時的順序,可以在這邊加以設定。當一個部隊死亡後,除非AI的資料不足或是有特定條件,否則AI會將它換掉。在這邊,有五種建築優先權的欄位:

生產 - 要建造、研發或是昇級什麼東西。

總數 - 追蹤相同類型建築物的數量。不在括弧中的數字表示AI擁有的總數。括弧中的數字只是表示城鎮數量。

食物 - 追蹤食物的使用程度。當優先權讓食物的耗損數量超過食物供應上限時,優先權會變為紅色。

城鎮 - 指定建造順序。

條件 - 如果在這邊指定的條件不合,AI就會略過這個建築物的優先權,並進行下一項。這邊的條件可能是在「一般」標籤之下設定的,或是為這個優先權特別設定出來的。

採金工人 - 選擇哪一個部隊做為AI開採金礦的部隊。在可以可以選擇的項目,視你在「一般」標籤中設定的種族而定。

伐木工人 - 選擇哪一個部隊做為AI開採原木的部隊。在可以可以選擇的項目,視你在「一般」標籤中設定的種族而定。

採收優先權 - 在這邊可以指定AI採收資源的優先權。在開採優先權方面有四個欄位:

採收 - 你想要工人採收的資源。

工人 - 有多少工人共同相同的優先權設定。

城鎮 - 工人開採的地點設定。

條件 - 如果在這邊所指定的條件未能達成,則AI會略過這個開採優先權並跳到下一個項目。這個條件可以是「一般」標籤中設定,或者它也可以為這個優先權特別設定。

 
[url=]進攻(Attacking)[/url]
 
攻擊群組 - AI的攻擊群組,可以在這邊表列或是創造。

目前的群組 - 攻擊群組可以在這邊加以定義。這邊有三個欄位,用來容納各種不同的攻擊群組。

部隊類型 - 部隊的種類。這個部隊是否可以選用,決定於你在「一般」標籤中的種族設定。

數量 - 這個部隊的數量,是否符合你所選定的部隊類型。

條件 - 如果在這邊指定的條件無法達成,目前的群組就不會將這一條資料納入。這個條件可以在「一般」的標籤之下創造,但也可以為這個優先權特別設定。

攻擊波潮 - 在這邊可以排定你的攻擊波潮。每一個攻擊群組中都有三個欄位。  # - 攻擊波潮編號。這可以作為整數的比較條件。

攻擊群組 - 你可以在這邊輸入攻擊群的名稱,編成攻擊群組。

延遲 - 下一波攻擊開始前的時距。


最小隊伍 - 要派出一波攻擊的最小部隊數量。

初始延遲 - 在第一波攻擊之前的等候時間。

重複攻擊波潮 - 在這邊設定攻擊時要分幾次,從最後一次之後多久再重複相同的攻勢。

目標優先權 - 旗下攻擊波潮鎖定的目標。在這邊有二個欄位。


目標 - 選擇AI的攻擊目標。在列表中越高的目標,其優先權越高。

條件 - 如果在這邊指定的條件無法達成,在攻擊時會略過這個目標。這個條件可以在「一般」的標籤之下創造,但也可以為這個優先權做專有的設定。

 
[url=]測試設定(Test Configuration)[/url]

這個標籤是AI專屬的項目,可以用來在正規戰地圖中進行測試。如要用於自定地圖,可以用匯入管理員匯入一個已匯出的AI檔案,來測試地圖的指令。

遊戲速度 - 在進行AI測試時變更遊戲速度。

遊戲選項 - 關掉戰爭迷霧,讓你可以清楚的看到整個地圖。你可以關掉勝利/失敗的條件,以免出現不必要的干擾。

地圖檔案 - 設定AI用來進行測試的地圖。

玩者 - 在這邊可以設定個人玩者的相關資訊,可以設定的項目如下:

控制者 - 選擇這個欄位的控制者。

種族 - 選擇這個控制者所使用的種族。

隊伍 - 選擇這個控制者隸屬於那一個隊伍。

顏色 - 選擇控制者的團隊顏色。

障礙設定 - 選擇控制者遭受的不良局勢。

AI - 如果控制者是選定為電腦,在這邊可以選擇要使用的AI。

AI困難度 - 如果控制者是選定為電腦,在這邊可以選擇AI的難易度。AI的難易度可以視為你的AI條件。

AI腳本 - 如果控制者設為電腦,且AI設為自定,可以在這裡匯入AI。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 06:49 PM | 显示全部楼层
音效編輯器(Sound Editor)

音效編輯器可以讓你匯入並匯出音效(.wav)檔案與音樂(.mp3)檔案,並透過觸發編輯器中的觸發來播放。要打開音效編輯器,使用F5或是選擇模組選單中的音效編輯器。
你想要在玩魔獸爭霸時,聽的是貝多芬的第九交響曲嗎?嗯,現在你可以試試看了。不過你還是要小心,因為Battle.net不會讓你把超過4MB以上的地圖轉到他人的電腦上,把音樂與音效匯入你的地圖檔案,會因為你匯入的資料太大,而導致Battle.net中止傳遞地圖的動作(不過,使用遊戲中的音樂,不會增加地圖的大小)。

音樂與音效是分為二個不同的部份。左側(類似地形編輯器中的筆刷列表)是所有內部採用的聲音,你無法變更這張列表中的內部音效。要在你的觸發中使用內部的音效或是音樂,只要選擇這個檔案,然後選擇「使用內部音效」或是「使用內部音樂」,接下來音效或音樂會出現在右側的音效或是音樂列表中。
這個列表的右側,包括了你先前匯入以及內部所使用的音樂與聲音。
只要一個檔案出現在檔案列表中,你也可以藉由雙擊一個檔案,來播放音效或是音樂,或是在點選想用的檔案之後,再點選工具列中的「播放音效」按鈕。要停止音樂或是聲音的播放,只要點選空白鍵或是選擇工具列中的「中止所有音效播放」功能。

要編輯一個選擇的音效或音樂檔案的內容,只要在它出現在右側的列表中,或是點選它之後再選擇「編輯音效內容」或是選擇「音效變數更名」。音效內容有下列的選項與資訊:


檔案 - 音樂或是音效的檔案名稱。

格式 - 音樂最大的KHz數、位元傳輸率(對.mp3檔案格式而言)或是取樣頻率(對.wav檔案格式而言)以及頻道的數量(對.wav檔案格式而言)或是編輯方式(對.mp3檔案格式而言)。

長度 - 音效的播放時間。

變數 - 這個變數名稱會出現在觸發編輯器中的音效變數列表中。對一個音樂檔案而言(.mp3),這是唯一可以變更的選項。

選項 -   循環 -音效檔案會不斷的重播,直到你下令停止。
             3D 音效 - 音效將會有3D角度,而且須要加以定位才能正確的播放。

            在超出範圍時中止 - 音效檔案將會在使用者超出有效範圍時停止。

音量 - 增加音效的相對音量。


淡入速率 - 控制音效淡入的速率。數字越大,則音效淡入的速度就越快。預設值為立即。

淡出速率 - 控制音效淡出的速率。數字越大,則音效淡出的速度就越快。預設值為立即。

音調 - 增加這個數字,可以增加音效播放的速率。

音效 - 可以在一個音效中加入特殊的效果。不過,這些效果只能與特定的音效卡相容。

最小距離 - 要聽到這個音效,至少要靠近到什麼程度的距離。

最大距離 - 在距離多遠時,還可以聽到這個音效。

切斷距離 - 音效開始淡出的距離。


要把這些音效用在你的地圖之中,你必須透過觸發編輯器。當你在匯入一個音效或是音樂的檔案,或是把內部的聲音或是編輯器右側列表中的音樂加上去後,你可以在透過「音效 - 播放音效」或是「音效 - 播放音樂」的方式,在觸發編輯器中進行播放。
記住,3D聲音必須與附加在特殊的地點上面,而且一定要放在部隊或區域的身上,你也走得夠近才會播放出來
回复

使用道具 举报

 楼主| 发表于 8-1-2007 06:52 PM | 显示全部楼层
物件編輯器(Object Editor)


物件編輯器可以讓你自定部隊、物品、飾物、技能與昇級。這些物件之後可以放在你的地圖上面,或是將之匯出並用在戰役編輯器或是人工智慧編輯器中。每一個物件最多可以擁有11種不同的類別變動。下面就對每一種物件的類型做簡要的介紹,並提供一些範例。

[url=]部隊(Units)[/url]

技能  -  變更部隊所擁有的技能,以及遊戲展開後這個部隊馬上可以使用的技能。這將包括了技能標籤中的任何技能。

美術  - 變更這個部隊的外觀。舉例來說,你可以在這邊調整部隊的模型、顏色、大小、角度和圖示介面。

作戰  - 變更這個部隊在戰鬥中的行為。包括了下列的項目:攻擊時的樣子、攻擊的頻率、造成的傷害、攻擊發出的聲音,以及攻擊的有效範圍。

編輯器  - 變更這個部隊在編輯器中的處理方式,包括了這個部隊會出現在哪一個編輯器的選單中,以及這個部隊死亡之後會掉下什麼物品。

移動  - 變更這個部隊是怎麼移動的。包括了這個部隊在群組中的陣型優先順序,部隊的基本速度、部隊轉身的速度,以及這個部隊是否能夠飛行。

路塊  - 變更部隊尋找路徑方式,包括了部隊的碰撞以及人工智慧如何處理這個部隊。

聲音 - 變更部隊所發出的聲音。像是部隊在移動、死亡或是被選擇時所發出的聲音。

屬性  - 變更部隊的屬性,包括了這個部隊的建造成本,生產以及耗損的食物量,生產所花的時間,是屬於哪一個類型(機械化部隊,城鎮大堂),修理所需的費用,這個部隊的生命點數高低,以及部隊擁有多少法力。

科技樹  - 變更這個部隊在科技樹中的位置。這包括了這個部隊可以昇級的項目,還有這個部隊需要什麼樣的建築物才能生產。

文字  - 變更這個部隊的文字介面,包括了下列的項目:部隊名稱,滑鼠移到部隊上面所出現的提示,以及部隊的描述。
 
[url=]物品(Items)[/url]

技能 - 變更這個物品所擁有的技能。這包括了技能標籤中的任何技能。

美術  - 變更這個物品的外觀。包括了下列項目:這個物品的顏色,這個物品放在地上時所使用的模型,以及這個物品在物品欄所顯示的圖示。

作戰  - 變更一個物品的特質,來影響它在受到攻擊時的反應。

屬性 - 變更物品的屬性,包括了這個物品的等級、是否會掉落或是可出售,在商店中最多可同時出售的數量,以及物品在商店中的補充速度。

文字 - 變更物品的文字介面,包括了物品名稱,滑鼠移到物品上面所出現的提示,以及物品的描述。

[url=]可毀物(Destructibles)[/url]

美術 - 變更這個可毀物的外觀。包括了模型、顏色與高度。

作戰 - 變更可毀滅物品的本質,來影響它在受到攻擊時的反應。

編輯器  - 變更可毀滅物品在編輯器中的處理方式。包括了這個可毀物會出現在哪一個編輯器的選單中,以及這個可毀物的放置地點 。

路塊  - 變更可毀物尋找路徑的方式,像是定義了部隊是否能踏上可毀物。

聲音 - 變更可毀物所發出的聲音,像是在毀壞時所發出的聲音。

屬性  - 變更可毀物的屬性,像是它的生命點數、建造時間、以及修理所需的黃金和原木。

文字  - 變更可毀物的名稱。


[url=]飾物(Doodads)[/url]

美術  - 變更飾物的外觀。包括了模型、顏色、大小和高度。

編輯器  - 變更編輯器對這個飾物的對待方法。包括了飾物會出現在哪些編輯器的選單中,以及飾物可以安置的地點。

路塊 - 變更飾物尋找路徑的方式,像是定義了部隊是否能踏上飾物。

聲音 - 變更飾物所發出的聲音,像是飾物毀壞時所發出的聲音。

文字  - 變更飾物的名稱。


[url=]技能(Abilities)[/url]

美術  - 變更這個技能的外觀,包括了這個技能所使用的圖示,這個圖示位於部隊指令卡中的位置,這個技能作用時的效果,以及這個技能生效時所附帶的模型。

資料 - 變更這些專屬於特定技能的欄位,像是反魔法對召喚生物所造成的傷害,治療術回復的生命點數高低,以及還魂術會創造出哪些兵種。

聲音  - 變更這項技能施展時的聲音。這包括了初始的聲音,以及任何繼續播放的音效。

屬性  - 變更一項技能的屬性。包括了廣域效果、等候時間、施展時間、法力耗損以及可以攻擊哪一類的目標。

科技樹  - 變更一項技能的科技樹需求。這包括了變更部隊,以及使用一項技能的基本等級。

文字 - 變更一項技能的文字介面。包括了技能的名稱、滑鼠移到技能上面所出現的提示、技能的描述以及指定的熱鍵。
 
[url=]昇級(Upgrades)[/url]

美術  - 變更昇級項目的外觀。這包括了一項昇級所用的圖示,以及這項昇級在部隊的指令卡中使用哪一個圖示。

資料 - 變更特定昇級項目的欄位,包括了鑄鐵劍的攻擊加成、拒馬的傷害加成,以及穿刺之箭的穿刺效果。

屬性  - 變更一項昇級的屬性。包括了所需的黃金和原木,有幾個等級,以及研發所需要的時間。

科技樹  - 變更昇級所需要的科技樹需求。這包括了變更一個部隊要研發昇級之前,所需要的等級。

文字  - 變更昇級的文字介面,包括了昇級的名稱、滑鼠移到昇級上面所出現的提示,以及昇級的描述。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 06:55 PM | 显示全部楼层
  • WE常用小技巧
  • 一般
    • 善用剪下(Ctrl+X)、複製(Ctrl+C)、貼上(Ctrl+V)、刪除(Delete):這幾個Windows常用指令在WE也是處處行得通,可以省下很多時間
    • 用鍵盤快速跳位。例如目前在:


      按下U之後就能立刻跳到首字為U的地方:


      然後再配合上下方向鍵,就能快速找到你想要的東西。

      如果是中文也一樣,轉成中文輸入法後,輸入中文字,就能跳到以它為首的地方;某些輸入法(如新注音)甚至可一次輸入多個中文字。
      其實在Windows及多處視窗型軟體也能用這個方法。
    • 撰寫更新歷史和注意事項:WE提供的註解有字元數限制,如果怕空間不夠,可以開一個觸發,轉成JASS,並把它停用(Disable;快速鍵Ctrl+I),就能寫空間無限的註解了。
      更新歷史和設計該地圖的注意事項通常相當重要,內建在地圖中比較方便,而且不會增加太多地圖容量,所以筆者建議這樣做。當然,如果要寫在別的地方也是可以。
    • 在WE中複製-貼上中文時,請先轉成中文輸入法再複製,要貼上時也要先轉成中文輸入法再貼上。否則可能會出現亂碼。
    • WE可以同時打開多個地圖,進行地圖間的資料轉移。可以從功能表的「視窗」選擇地圖,然後選定要複製的東西並複製,再從「視窗」選擇要貼上的地圖貼上東西,非常方便!!
    • WE常會有為數不少的功能要測試,建議大家自己設計一張小型的、測試功能專用的地圖來測試。不要每次想測什麼都直接加到自己寫的一張很大的地圖裡測,這樣速度是差很多的。
  • 地形編輯與物件擺設
    • 先大致決定好座標再畫圖,這樣畫出的圖會比較準。尤其要畫一張對稱的地圖時,定座標的動作更是不可少
    • 記住,選取色板上的物件後,可以在主畫面擺設物件;不選取時,可以選擇主畫面的物件並加以設定(按Enter或點兩下)。
      按下空白鍵可以切換色板的選取、不選取狀態(會自動記住之前選取的類型)
    • 移動瀏覽畫面的位置:
      • 按方向鍵的↑↓←→
      • 按住滑鼠右鍵拖曳
    • 調整攝影機視角:
      • 按住Ctrl後,按方向鍵的↑↓,可以上升/下降攝影機
        按住Ctrl後,按方向鍵的←→,可以左旋/右旋攝影機
      • 按住Ctrl後,按住滑鼠右鍵拖曳,可以快速調整攝影機的視角 ,包括左旋、右旋、上旋、下旋
        使用滑鼠滾輪可以上升/下降攝影機
      • 不小心把視角調亂時,可用「檢視」→「切換到遊戲攝影機」(Ctrl+Shift+C)切回預設視角
    • 選取一塊地形後,可以利用「編輯」的鏡射、左右旋轉、旋轉180度等功能做調整;
      或者先按下複製、貼上,在準備貼上時,利用「編輯」的鏡射貼上、旋轉貼上調整剪貼簿內容,再進行貼上。
    • 選取物件之後,按住Ctrl再用滑鼠左鍵點擊一個地方,即可使所有選取的物件面向該處
    • 選取物件之後,使用「編輯」→「推動選取的物件」中的快速鍵可以更快速地做你想要的設定(緊按亦可):
      按數字區的1 2 3 4 6 7 8 9可以微調物件位置,甚至放到滑鼠不容易放到的地方
      按數字區的/ *可以稍微旋轉物件位置
      按數字區的+ -可以放大或縮小
      按Home、End可以在XY軸方向放大或縮小
      按Page Up、Page Down可以在Z軸方向放大或縮小
    • 使用「檢視」的功能切換想看和不想看的東西,或者鎖定視角等,以便更清楚、精細、不受干擾地設定想設定的東西
    • 善用「進階」的置換功能改變已放置的部隊、飾物、地形等等,尤其是部隊身上己設置了許多相關的觸發時更為有用,因為置換部隊會自動同步更新觸發。
    • 不同用途的區域可以設成不同的顏色以利辨識
    • 可以用物件管理器(F11)找尋物件,並且做檢視和刪除
  • 物件編輯器
    • 利用種族、戰役(Campaign)、特殊(Special)為部隊分類;物品或其它同理
    • 利用「檢視」的功能開關項目,以便更快地尋找和編輯你想設定的欄位
    • 選取一個物件,按下複製再按下貼上,就可以快速地以它為底創造出一個新物件
    • Ctrl+D是切換以原始資料顯示數值,非常重要!絕對不要忘記!
  • 觸發編輯器
    • 沒人規定一定要用英文,能寫中文的地方可以盡量使用中文
    • 暫時不用的觸發或觸發中的一行指令可以先停用(Ctrl+I、Ctrl+F)而不必急於刪除
    • 可以用物件管理器(F11)找尋你要的觸發或變數,以及檢視它們相互調用的情形,尤其可以輕易看出是否有變數未被觸發使用,方便你找到和刪除垃圾。在研究他人的地圖時 也特別有用,它能幫助你了解整體的架構。
    • 可以設計一些作弊碼以利測試;作弊碼建議限制單機使用以免你忘了停用而讓別人發現和濫用:
       
      Init
       Events
        Map initialization
       Conditions
       Actions
        Custom script: set udg_IsSingleGame = bj_isSinglePlayer
      這是判斷是否為單人遊戲的設定,其中IsSingleGame是自己定的變數。這裡是直接撿現成,用b社已判斷好的變數值,如果你要自己計算玩家數也可以。
       
      Debug Level Up
       Events
        Player - Player 1 (Red) types a chat message containing -level as An exact match
       Conditions
        IsSingleGame Equal to True
       Actions
        Unit Group - Pick every unit in (Units currently selected by (Triggering player)) and do (Hero - Set (Picked unit) Hero-level to 99, Show level-up graphics)
      這是典型的作弊碼寫法,應該不用多作解釋吧?
       
    • 多利用註解,或者用註解功能畫分隔線,日後修改會較方便,不會自己看了都一頭霧水。註解的原則基本上就是「把自己當作是讀者」來寫,越詳細越好。
      除非日後不會再修改這個地圖、很快就能做好、或者沒有保護程式怕被盜改等特殊原因,否則筆者建議大家養成加上註解的習慣。
    • 暫存變數是一個相當實用的技巧,用得好可以簡化複雜的動作,通常像實數型的用x、y、z;整數用a、b、c;點用P1、P2、P3;部隊用TempUnit;玩者用TempPlayer;物品用TempItem
    • 利用副程式:不同觸發可以用Trigger - Run <Trigger> (checking(ignoring) conditions)互相調用。利用這點,可以把常用的一連串動作設計成沒有Events的觸發當作副程式。
      然後在主要的觸發用Trigger - Run <Trigger>進行呼叫,以增加便利性,也較方便修改。
    • 善用Add Event:如果你要把一些特定的部隊加入日後的事件,可以考慮用Add Event。最典型的範例如樹木復活
    • 使用單行JASS設定區域變數,以解決一般變數在等待中被修改的問題。要這麼做只要學三個函數就夠了:
      local [變數名稱]................................必須寫在最前面
      local [變數名稱] = [變數初始值]........必須寫在最前面
      set [變數名稱] = [變數值]

      技巧上來說:
      Custom script: set 區域變數 = udg_全域變數
      Wait
      Custom script: set udg_全域變數 = 區域變數
    • 使用單行JASS設定「本機玩者」以便對特定玩者播放音效或者執行類似動作
    • 對於一些想在GUI觸發中直接使用,但是必須用JASS取得的函數值,可以用在初始化時記錄在變數中,例如:
       
      Init
       Events
        Map initialization
       Conditions
       Actions
        Custom script: set udg_IsSingleGame = bj_IsSinglePlayer
        Custom script: set udg_LocalPlayer = GetLocalPlayer()
        Custom script: set udg_Locust = 'Aloc'
      如此要用的時候就輕鬆很多:
      Unit - Add Locust to (Triggering unit)
      If (LocalPlayer Equal to Player 1 (Red)) then do (Sound - Play BlizzardTarget1 <gen>) else do (Do nothing)
    • 程度高一點的可以學習有關記憶體漏失的問題,以優化地圖,減低不必要的延遲和資源浪費
  • JASS撰寫
    • 暫時不用的JASS語句前加上//以達到停用單行JASS的目的。
    • 利用ExecuteFunc來新增執行緒,參數問題可以借用blizzard.j的共用變數,或者自訂全域變數來傳送。
    • 寫JASS要學習動態、靈活地增刪物件,尤其是觸發器,使它們在不需要時不存在,需要時立即可被調用。如此便可省下不必要的資源浪費。
    • 常用到的特定步驟,就可以考慮製成一個函數,如此便可精簡程式碼,日後也容易做統一性的修改,這便是模組化。
    • 利用回傳錯誤和遊戲快取做資料連結,只要有其中的某個物件,就能夠取得其它相關的物件。如此便能做出支援多重施法的高階技能。
  • 技能製作
    • 使用隱藏部隊達到合併技能效果、單體技群體化、一般技改為自動施展等
    • 利用有蝗蟲技能的部隊做特效,以便做出不同大小、高度、顏色、透明度的特效效果
    • 使用連結做為觸發技能的基底
    • 使用法術書做出多項選擇的技能
    • 隱藏被動技圖示:把被動技放在法術書內,把法術書用觸發關閉,然後添加法術書給部隊,部隊就會得到隱藏的被動技。
    • 使用暴風烏鴉技能以便用觸發改變非飛行部隊的飛行高度。如果不想看到圖示,可用觸發關閉之
    • 使用浮動文字做出字幕效果,一般方法是:創造、設位移、設時限、設壽命、設衰退點
    • 使用觸發加入特效和音效,以增加技能的華麗度
    • 利用科技需求做為技能的限制。例如要讓英雄變身後就不能用技能,可以把它的技能加入一個科技需求:[變身前的英雄]
      ※注意是否允許科技重疊(單玩家多個重複英雄的情形)。
    • 使用觸發Enable/Disable Ability做為技能的限制,和科技需求不同的是,被停用的技能不會顯示、不能學習,而未達科技需求的技能仍會顯示出圖示和說明,也可以學習。
      ※注意是否允許科技重疊(單玩家多個重複英雄的情形)。
    • 利用Turn On/Off以及時間事件,做出間隔時間短的細微動畫(卡通原理)
      ※注意是否支援多重施法
    • 使用觸發技能時要注意技能可否重學、可否重設冷卻時間(有些技能牽涉到變數記錄,不能在一次技能生效期間施展第二次)、可否改變施法者的所有權、可否一個玩家多個施法者、可否用Spell Shield……等等可能造成錯亂的狀況


[ 本帖最后由 xtricky 于 8-1-2007 06:57 PM 编辑 ]
回复

使用道具 举报

 楼主| 发表于 8-1-2007 06:59 PM | 显示全部楼层
觸發器基礎教學
By Danny
0、前言:
      終於進行到最重要也是最難的一個課程了,玩過單人任務都會知道單人關卡充滿豐富的遊戲事件,遊戲可以創造的事件非常多,從自訂勝利條件、 部隊自動做某樣事情、天氣變動、遊戲電影等等都可以從事件創造區設定出來。WE的Trigger大多人都稱為「觸發器」,是專門編輯遊戲所有的人事物的事件,例如部隊進入指定區域發生怪物傾巢而出的事件,就是所謂的遊戲事件。然而並不是很多人都了解如何編輯遊戲事件,甚至光是看到觸發器的編輯介面就嚇跑了許多使用者,其實仔細去研究觸發器的話,你會發現觸發器是WE中最好玩的項目之一。

      當你熟悉WE內的觸發器之後,一定會覺得WE實在是太好玩了,一不小心就會用的太過愉快而造出太龐大太複雜而讓遊戲緩慢的任務地圖。儘管如此,即使Blizzard手上有WE這麼好的工具,但是他們還是花了相當多的時間來設計「魔獸爭霸3」中的任務關卡地圖。雖然用WE設計一個關卡要花掉數天的時間,但是後面的測試工作才是最困難的,設計者往往要耗費比設計關卡更多的時間在地圖中測試,並為單人與多人模式地圖調整出最佳的遊戲參數與設定。所以有人說,當你用編輯器正式完成一個關卡時,你不會再想去玩它一次的,這句話果然沒錯……。

  請讀者記住:所有人都有能力使用&編輯觸發,你不必去了解程式語言或是精通英文才能夠接觸觸發來編輯事件,只要你能把觸發是當作 「拼圖遊戲」來看待的話,相信以後觸發不會像是天書一樣讓你望之卻步。

由於觸發器的範圍太過於龐大,建議新手的學習順序是:
1.觸發器事件基本原理:本文
2.變數(陣列)、延遲、迴圈(For、Pick)的概念:觸發器使用教學
3.觸發器中英對照表
4.演算法/製作 練習:可以試著做做看F.A.Q的問題與範例解答
5.JASS:JASS教學
一、基本操作:
  • 介面介紹:
    如果你對觸發器的使用介面完全不了解,建議你先閱讀官方說明手冊(本手冊有內附),或者動手去熟悉它。
    • 先從最常用的功能開始講起好了:


      上圖中左邊數來第五組第一個是創建新資料夾。一個觸發被放在哪個資料夾並沒有任何影響,一般是做為分類用。
      例如與生產小兵相關的觸發放一個資料夾;與遊戲初始化相關的放一個資料夾;與測試除錯相關的放一個資料夾等等。
      資料夾可以把它改成註解形式,這樣它的外觀會有一點改變。一樣主要是分類用,例如當做分隔線。

      第五組第二個是創建新觸發。有時也可以複製/貼上已存在的觸發再改名改內容。

      第五組第三個是創建新註解,註解也是用來做分隔和分類的,裡面可以寫一些字,但有字元數的上限。

      第六組的三個分別是在一個觸發器中加入新的事件(Event)/條件(Condition)/動作(Action),以後會常常用到。

      第四組唯一的一個按鈕是用來管理變數的,按下它可以開啟變數管理器,以在裡面新增/修改/移除變數。
    • 還有一個很常用的是功能表中的編輯(Edit)功能:


      上面數來第五組的Enable Trigger是啟用/停用觸發,當觸發被停用時,就不會被編譯,也不會在遊戲中被執行,通常是為了測試目的暫時把一個觸發停掉。

      Trigger is Initially On是用來設定一個觸發預設開啟或預設關閉,被關閉的觸發不會有作用,但是可經由其它的觸發開啟而得以使用。通常是用來做一些遊戲的調控。

      Enable Function是用來啟用/停用一個觸發中的一行敍述,和啟用/停用觸發一樣,通常是為了測試目的。

      Category is Comment是用來設定資料夾是否為註解,上面有說明過。

      Convert to Custom Text是用來把觸發轉成JASS碼做編輯,雖然會變得較為難懂,但功能比一般的觸發更多。
      另外,轉成JASS以後就不能轉回來,最多用還原功能回復轉換前的樣子。

      Copy As Text可以用來把觸發(或觸發中的幾行所有事件/所有條件/所有動作)複製成文字,方便你在別的地方貼出來問人。
      但是大多數的討論區無法對齊半形空白,建議可以用記事本之類的文字編輯器把多個半形的空白(    )取代成全形的空白( )以使排版美觀。
      還有,這項功能複製出的中文會變成亂碼,請手動修改它吧。(沒辦法,老外不會管中國人的死活)
  • 撰寫觸發:
    假設現在別人隨便貼了一條觸發--
    Complement
     Events
      Unit - A unit Dies
     Conditions
      ((Dying unit) is A Hero) Equal to True
     Actions
      Player - Add 100 to (Owner of (Dying unit)) Current gold

    哇!看起來好複雜,要怎麼寫呢?請一步一步跟著做:
    • 首先,按下[創建新觸發]按鈕創造觸發,並且把它命名為Complement
    • 按下[創建新事件],創造一個事件,你會看到這個:

      你可以在Map Initialization那一欄裡往下找,直到找到你要的為止。
      也可以在-All那裡往下拉到部隊(Unit)分類,以便使下面那欄只顯示出部隊類別的事件,再從中找尋。
      或者在-All那裡拉到搜尋關鍵字,並且搜尋你要的字。
      還有就是按下U,就會立刻拉到以U開頭的地方(中文版一樣,切換成中文輸入法再輸入中文即可)。

      總之,你應該會在選到Unit - Generic Unit Event時,看到Event Text那裡呈現這樣:

      是不是和你要的Unit - A unit Dies一模一樣呢?按下OK確認,此時你會發現Event下面已經多了這一行觸發敍述了。
    • 接著我們來加入條件。如果你是有經驗的WEer,根據((Dying unit) is A Hero) Equal to True,你應該可以直接看出應該去找Boolean Comparison;
      如果你沒經驗,你或許在每個都試過以後,發現Boolean Comparison是唯一可行的。總之,選到Boolean Comparison。

      裡面的內容是:

      似乎不太像我們要的?不過讀者有看到嗎?Click on the underlined sections to set values

      所以我們點一下((Triggering unit) is A structure),出現這個視窗:

      這是觸發編輯器的結構特色,每一個事件/條件/動作下或多或少有用到函數(Function)。
      每一個函數可回傳一個值,其內可能又有別的函數,就是像這樣一層一層地往下推。

      廢話不多說,點一下(Triggering Unit),接下來又會出現一串選項,選到Event Response - Dying Unit,按下OK,
      你會發現現在它改成了((Dying unit) is A structure)

      接著用同樣方法,把A structure改成A hero,然後連按OK-OK-OK,你的條件加好了。
    • 再來是動作,這個應該不用教了吧?用同樣的方法一層一層寫就好了
    • 一定會有人問--為什麼你一看到動作Player - Add 100 to (Owner of (Dying unit)) Current gold,就知道要找Player - Add  Property呢?
      理由很簡單--就是經驗。等你熟悉以後也能這麼快,不必一個一個選項龜速地看。
  • 設定變數:
    有時候我們會看到這樣的觸發:
    Set Barrack Count
     Events
      Unit - Barracks 0001 <gen> Dies
     Conditions
     Actions
      Set BarracksCount = (BarracksCount - 1)
      Multiboard - Set the text for (Last created multiboard) item in column 1, row 1 to (String(BarracksCount))
     
    • 上面的Barracks 0001 <gen>後會有寫個<gen>,代表那是指向一個地圖預置的東西,而編號是由WE自動產生的。
      在事件裡選到Unit - Specific Unit Event,下面的Unit按下去之後,電腦會讓你選取一個已經被擺在地圖上的部隊,你可以擺一個兵營然後選取它,
      編號或許不是0001,但是那不要緊,只要你知道那代表的是那一個兵營即可。
    • 下面的Set BarracksCount = (BarracksCount - 1)可在動作的Set Variable那欄找到,
      可是當我們按下Variable
      時,可能會像下圖一樣,發現一個選項都沒有:


      這表示你尚未建立變數,按下Edit Variables以後,會出現一個讓你設定變數的視窗,
      按下上面第三組第一個鈕(應該是唯一能按的鈕)建立新變數,名稱輸入BarracksCount,當然你可以視需要改成別的名稱
      類型選擇整數(Integer),然後按OK,此時Variable那個視窗就會出現BarracksCount讓你選擇了。

      一定又有人會問,為什麼要選Integer?選別的會怎樣?你怎麼知道要選Integer?
      呃,你可自己試試看不選擇Integer會有什麼不一樣...
      至於我怎麼知道要選Integer,一樣也是靠經驗,因為Set BarracksCount = (BarracksCount - 1),後面顯然是一個整數。
    • 最後一行讀者你應該知道要怎麼設定了吧?
      說實話,如果前面沒講到,你可能找破頭也沒辦法在String選項下面找到BarracksCount這個選項,
      所以這個又要經驗了,內行的人一眼就知道那是一個變數,因為它不像是一個完整的文句,
      變數的取名是有限制的,只能用英數、不能用空白(通常用底線_代替),所以看起來會和一個函數的語法不太一樣。

      當然,初學者難免分不太出來,可能全部函數都找過了,發現找不到,才終於想到那是一個變數。
      這個沒有辦法,誰叫你是初學者?凡事總是有個起步啊。
    • 變數是什麼?好問題,欲知詳情,請看下文。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 07:01 PM | 显示全部楼层
二、基本原理:
  • 事件(Event)
    事件將會啟動一個程序,可能導向一個觸發的啟動。當觸發器中設定的事件在遊戲中發生了,該觸發就會啟動。如果一個觸發器有多於一個事件,只要發生其中一個,就會啟動觸發。

    事件中只要含有至少一條「Map initialization(地圖初始化)」,都會在遊戲載入(loading)時執行。當你開始一個遊戲,出現一個Loading畫面和一個在跑的Loading光條時,電腦在做什麼?除了載入地形、放置飾物、擺設部隊以外,就是執行這些被設定要在初始化執行的觸發。請注意有些觸發無法在載入時執行,一般我們會使用「Time - Elapsed game time is 0.00 seconds」讓它在遊戲開始之後立刻執行。

    常見的事件有:每經過XX秒、「任一個」部隊死亡、「任一個」部隊開始施展某項技能等
  • 條件(Condition)
    條件是特殊的需求,決定行動的運作與否;所有的條件必須都是「True(真)」 ,才能讓一個觸發的行動運作。事件所涵蓋的範圍通常很廣,但不是所有的事情你都想要啟動觸發,所以條件存在的目的就是要過濾出想要的事件,來決定是否執行行動。

    舉個例子來說,有個觸發是這樣的:
    Complement
     Events
      Unit - A unit Dies
     Conditions
      ((Dying unit) is A Hero) Equal to True
     Actions
      Player - Add 100 to (Owner of (Dying unit)) Current gold

    這個條件可以篩選死亡的部隊是否為英雄,假設一個部隊死亡了,而它剛好是個英雄,則條件((Dying unit) is A Hero) Equal to True符合,就會給死亡者100黃金做為補償。如果死亡的部隊不是英雄,則條件((Dying unit) is A Hero) Equal to True顯然不成立,那就什麼也不會發生。
  • 行動(Action)
    一個觸發的主要內容,敘述當這觸發被啟動且條件符合後要做哪些事。可能是殺死某部隊、在某兩點間製造閃電效果、給予某玩家XX金錢等。行動可以讓設計者全面控制遊戲中所發生的事。觸發中真正需要的唯一內容就是行動(一個沒有行動的觸發不會對遊戲造成任何影響,有寫和沒寫豈不是一樣?)。很重要的一點是,觸發並非一定要靠著條件或事件,才能執行所設定的行動。觸發也可以被其它的觸發呼叫並執行,像是"Trigger - Run (checking/ignoring conditions)"。
回复

使用道具 举报


ADVERTISEMENT

 楼主| 发表于 8-1-2007 07:02 PM | 显示全部楼层
三、基本概念:
  • 變數
    如果把電腦的記體體當做是一連串的櫃子,那麼變數就像是已被使用並貼上標籤的櫃子,可讓使用者自由存取。其中,變數名稱就是貼上的標籤的名稱,變數的值就是櫃子裡存放的東西。所以:
    定義變數XXX,就好像在一個大房間裡,找一個沒有標籤的櫃子,貼上寫著「XXX」的標籤。(如果已經有個叫「XXX」的變數存在,我就不能再定義它。一般在這種情形下程式會出錯)
    設定XXX變數的值,就好像去找貼著「XXX」標籤的櫃子,把東西存放進去。
    取出XXX變數的值,就好像去找貼著「XXX」標籤的櫃子,把裡面的東西拿出來用。(不過電腦的世界和現實世界不太一樣,電腦拿完東西使用以後,東西不會消失,也就是說,讀取變數後,那個「XXX」櫃子裡的東西仍然存在。)
    修改XXX變數的值,就好像去找貼著「XXX」標籤的櫃子,把裡面的東西拿出來丟掉,再放一個新的東西進去。

    變數有什麼用處呢?舉個例子來說,假設我在3分10秒時創造了一個英雄--死亡騎士阿薩斯。然後,我想設定「當遊戲進行到30分鐘時,巫妖王派遣二個末日守衛保護阿薩斯」,我當然要再創造二個末日守衛,可是地點呢?我有辦法告訴電腦地點是「3分10秒時創造的英雄的目前所在地」嗎?當然是沒有辦法的。為了解決這個問題,我必須在創造阿薩斯的時候,用變數把它記錄下來,假設變數叫做arthas,如此一來,在30分鐘時,我就可以叫電腦「創造二個末日守衛於arthas的目前位置」了。簡單來說,凡是「溯及既往」的事,就需要用到變數。

    如果此時老師問我「上次的數學考幾分?」,我回答80分,為什麼我能夠回答呢?因為之前發數學考卷的時候,我有把分數記下來;如果數學考卷發下來我卻沒有記得分數,那麼此時我就沒有辦法回答老師。同樣的,我如果要電腦給我之前某時刻的某資料,當然就必須在那個「某時刻」命令電腦把它記憶下來,而記憶的方式就是用變數。不過人和電腦有一點點不同--人會把所有事記下來,久了就忘掉;電腦只記我命令它記的東西,但是永遠不會忘掉。

    此外,變數有分類型,如整數、實數、部隊、...,這就好像人的記憶有文字、圖像、聲音、...一樣。我們不能把文字當成圖片來記,除非先把文字轉成圖片。同樣的,如果我想讓電腦用整數的方式把實數記下來,就得先把實數轉成整數,才能儲存到整數類型的變數中,像這樣: Set N = Integer(3.8)。不過這樣一來,電腦存的是3而不是3.8,小數點的部分就遺失了。這好像我們如果把文字用圖片的方式記憶,或者用言語描述一個景象(圖片轉成聲音),就 會有失真的現象。

    什麼時候要使用變數呢?基本上這是一種經驗,大家多看演示,多思考就知道了。

    變數常常用在需要一個地方暫放資料的時候。例如我要交換A、B兩部隊的hp,我如果直接把A的hp改成B的hp,那要怎麼把B的hp改成A之前的呢?這已經讀取不到了。所以我建立一個變數X,先設定X = A的hp,然後設定A的hp = B的hp,最後是B的hp = X,如此一來就能順利完成了。在此例中,變數X代表A「之前的」hp。

    有時單一功能不得已要分成多個觸發製作,例如擊退技能就是好例子,第一個觸發由施法啟動,然後開啟第二個觸發每0.0x秒移動目標使其後退。第二個觸發的事件和施法完全無關,此時要抓取施展目標是徒勞的,然而第一個觸發和施法有關,所以我就得趁著抓的到施法目標時,將其用變數紀錄,下一個觸發則從變數讀取。此例中,變數代表第二個觸發「之前」執行的第一個觸發的事件回應值。

    變數也用來記錄一個會隨時間不斷變動的量。假設在一個單機遊戲中,我想設定「當玩者英雄死亡時,殺死他的電腦玩者得到他生前殺人數50倍的賞金」,那麼要怎麼取英雄生前的殺人數呢?我可以設定一個記錄殺人數的變數叫做CountKills,然後建立一個觸發「當部隊死亡,且殺人者為玩者的英雄,則設定CountKills為CountKills+1」。接著我就再寫一個觸發:「當玩者英雄死亡時,給予殺人者50 x CountKills的黃金,並設定CountKills為0」。本例中,變數CountKills代表玩者英雄「之前的」殺人總數。

    有時我們事件會寫「Unit - Archmage 0000 <gen> Dies」,那個Archmage 0000 <gen>是代表我在地圖上放置的大法師。事實上,由於我在觸發中使用到它,電腦會在地圖初始化的時候為它建立一個變數,以便我在遊戲中能夠讀取並操作那個部隊,標記<gen>就表示那是一個初始化時設定好的變數。

    Last created Unit、Last created special effect、...也是變數。當我用觸發創造部隊時,B社內部的函數會創造一個部隊,並且把它存到Last created Unit,以便我接下來對它進行操作。如果我創造了一個步兵,Last created Unit指的是那個步兵,我再創造一個火槍兵,這時Last created Unit指的是那個火槍兵,此時我就無法對步兵操作了,除非我在創造步兵之後先用一個變數記下來: Set xxx = Last created Unit,再創造火槍兵。
  • 陣列
    如果說變數是已被使用並貼上標籤的櫃子,那麼陣列就是被貼上標籤且編號的一整組櫃子。其中陣列名稱就是櫃子組的名稱,陣列索引值就是櫃子組中的櫃子編號,陣列的值就是櫃子中存放的東西。所以:
    定義變數XXX,就好像在一個大房間裡,找一大群沒有標籤的櫃子,貼上寫著「XXX」的標籤。(如果已經有個叫「XXX」的變數存在, 我就不能再定義它。一般在這種情形下程式會出錯)
    設定XXX[OOO]變數的值,就好像去找貼著「XXX」標籤的櫃子組中的第OOO個櫃子,把東西存放進去。
    取出XXX[OOO]變數的值,就好像去找貼著「XXX」標籤的櫃子中的第OOO個櫃子,把裡面的東西拿出來用。(不過電腦的世界和現實世界不太一樣,電腦拿完東西使用以後,東西不會消失,也就是說,讀取變數後,那個櫃子裡的東西仍然存在。)
    修改XXX[OOO]變數的值,就好像去找貼著「XXX」標籤的櫃子中的第OOO個櫃子,把裡面的東西拿出來丟掉,再放一個新的東西進去。

    承前面的例子,如果我想設定「當玩者英雄死亡時,殺死他的玩者得到他生前殺人數50倍的賞金」,但是這次是多人遊戲,裡面的12個玩家都有一個英雄,難道我們要用12個變數分別記錄?這時陣列的好用就出來了,我們可以寫一個觸發:「當部隊死亡,且殺人者是英雄,則設定CountKills[殺人者的玩者編號]為CountKills[殺人者的玩者編號]+1」(也就是如果玩者1殺人,則CountKills[1]計數加1;若玩者2殺,則CountKills[2]計數加1......),再寫一個觸發:「當一個英雄死亡時,給予殺人者50 x CountKills[死亡者的玩者編號]的黃金,並設定CountKills[死亡者的玩者編號]為0」,輕鬆解決這個問題。

    陣列也很常配合迴圈和隨機數使用。我可以在初始化時用陣列作表格,然後在遊戲中用迴圈來控制表格中的所有元件,或者用隨機數抽取表格中的任意一個。如果我想製作「每經過30秒,就在主堡隨機產生N個步兵、火槍兵、騎士、或法師」,可以先建立一個部隊類型的陣列UnitTypeList[],並且在初始化時,分別設定UnitTypeList[1]=步兵、UnitTypeList[2]=火槍兵、UnitTypeList[3]=騎士、UnitTypeList[4]=法師、...。然後就能寫「每經過30秒,在主堡產生N個UnitTypeList[Random integer number between 1 and 4]」;如果我要它輪流產生,可以寫「每經過30秒,設定i = i mod 4 + 1,在主堡產生N個UnitTypeList」;如果我要每30秒4種都出,可以用迴圈:「每經過30秒,for Integer A = 1 to 4,在主堡產生N個UnitTypeList[Integer A]」。上例中UnitTypeList[]就像是一個表格, 我可以抽取其中一個、其中幾個,或者其中全部:
    編號012345...
    資料(空)步兵火槍兵騎士法師(空)...

    魔獸的陣列是從0開始(一般程式都會從0開始,不過人的習慣一般從1開始),8191結束,即xxx[0~8191],總共8192個。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 07:03 PM | 显示全部楼层
For迴圈:
迴圈是一種讓電腦連續執行一段程式碼多次的功能,可分為一般程式都有的For迴圈,以及B社特別設計的Pick迴圈。
先看For迴圈,假設我們寫入以下的觸發:
 
Loop Test
 Events
  Player - Player 1 (Red) types a chat message containing -test as An exact match
 Conditions
 Actions
  Visibility - Disable fog of war
  For each (Integer A) from 1 to 3, do (Actions)
   Loop - Actions
    Game - Display to (All players) the text: (String((Integer A)))

  Visibility - Disable black mask
這段觸發會被轉成JASS碼儲存和執行,如下:
function Trig_Loop_Test_Actions takes nothing returns nothing
 call FogEnableOff( )
 set bj_forLoopAIndex = 1   -----------------------------------------------------設定變數IndexA為1

 set bj_forLoopAIndexEnd = 3   
-------------------------------------------------設定變數IndexAEnd為3
 loop
   ----------------------------------------------------------------------------進入迴圈
  exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd   
------------------------判斷當IndexA>IndexAEnd就跳出迴圈
  call DisplayTextToForce( GetPlayersAll(), I2S(GetForLoopIndexA()) )
  set bj_forLoopAIndex = bj_forLoopAIndex + 1   
-----------------------------設定IndexA的值加1
 endloop   
------------------------------------------------------------------------迴圈結束(執行至此會再回到loop)
 call FogMaskEnableOff( )
endfunction

//===========================================================================
function InitTrig_Loop_Test takes nothing returns nothing
 set gg_trg_Loop_Test = CreateTrigger( )
 call TriggerRegisterPlayerChatEvent( gg_trg_Loop_Test, Player(0), "-test", true )
 call TriggerAddAction( gg_trg_Loop_Test, function Trig_Loop_Test_Actions )
endfunction

它的用途就是重複執行迴圈內的敍述,可以用很短的文字敍述,執行很多遍類似的動作。以此範例來說,它會依序印出1,2,3。如果我把它改成For each (Integer A) from 1 to 100, ...,那麼就會印出1,2,3,...,100
 
Pick迴圈 Pick迴圈是b社用一些不可思議的方法寫出來的迴圈型式(原理?筆者也不知道=.=")。它可以對一 群部隊、玩家、可毀物中的所有對象做類似的操作。讓我們看看範例:
 
Pick Test
 Events
  Player - Player 1 (Red) types a chat message containing -test as An exact match
 Conditions
 Actions
  Visibility - Disable fog of war
  Unit Group - Pick every unit in (Units in (Playable map area)) and do (Actions)
   Loop - Actions
    Unit - Kill (Picked unit)

  Visibility - Disable black mask
同樣地,它也會被轉成JASS碼,如下:
function Trig_Pick_Test_Func002A takes nothing returns nothing
 call KillUnit( GetEnumUnit() )
endfunction


function Trig_Pick_Test_Actions takes nothing returns nothing
 call FogEnableOff( )
 call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function Trig_Pick_Test_Func002A )
 call FogMaskEnableOff( )    └──將Unit Group內的部隊選取,執行一段程式碼(Trig_Pick_Test_Func002A)
endfunction

//===========================================================================
function InitTrig_Pick_Test takes nothing returns nothing
 set gg_trg_Pick_Test = CreateTrigger( )
 call TriggerRegisterPlayerChatEvent( gg_trg_Pick_Test, Player(0), "-test", true )
 call TriggerAddAction( gg_trg_Pick_Test, function Trig_Pick_Test_Actions )
endfunction
假設全地圖有三個部隊,分別叫a,b,c。它的執行順序如下:
function Trig_Pick_Test_Func002A takes nothing returns nothing
 call KillUnit( GetEnumUnit() )   -----(3)  -----(4)   -----(5)
endfunction

function Trig_Pick_Test_Actions takes nothing returns nothing
 call FogEnableOff( )   -----(1)
 call ForGroupBJ( GetUnitsInRectAll(GetPlayableMapRect()), function Trig_Pick_Test_Func002A )   -----(2)
 call FogMaskEnableOff( )   -----(6)
endfunction   -----(7)

//===========================================================================
function InitTrig_Pick_Test takes nothing returns nothing
 set gg_trg_Pick_Test = CreateTrigger( )
 call TriggerRegisterPlayerChatEvent( gg_trg_Pick_Test, Player(0), "-test", true )
 call TriggerAddAction( gg_trg_Pick_Test, function Trig_Pick_Test_Actions )
endfunction
執行後結果很簡單,就是殺掉a,b,c三個部隊。
中斷(Skip Remaining Actions):
一般情況下,當程式執行到Skip Remaining Actions那一行時,會跳出目前正在執行的函式。如下:
 
Return Test
 Events
  Time - Elapsed game time is 5.00 seconds
 Conditions
 Actions
  Unit - Create 1 Footman for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees   -----(1)
  Skip remaining actions
   -----(2)    ------------------------跳出整個Actions
  Unit - Create 1 Rifleman for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
轉成JASS則為:
function Trig_Return_Test_Actions takes nothing returns nothing
 call CreateNUnitsAtLoc( 1, 'hfoo', Player(0), GetRectCenter(GetPlayableMapRect()), bj_UNIT_FACING )
---(1)

 return
---(2)   ------------------------跳出整個函數(Trig_Return_Test_Actions)
 call CreateNUnitsAtLoc( 1, 'hrif', Player(0), GetRectCenter(GetPlayableMapRect()), bj_UNIT_FACING )
endfunction


//===========================================================================
function InitTrig_Return_Test takes nothing returns nothing
 set gg_trg_Return_Test = CreateTrigger( )
 call TriggerRegisterTimerEventSingle( gg_trg_Return_Test, 5 )
 call TriggerAddAction( gg_trg_Return_Test, function Trig_Return_Test_Actions )
endfunction
回复

使用道具 举报

 楼主| 发表于 8-1-2007 07:04 PM | 显示全部楼层
四、進階概念:
  • 延遲
    電腦執行程式碼是不需要時間的,以下的實驗可以證實這個想法:
    Delay Test
     Events
      Player - Player 1 (Red) types a chat message containing -test as An exact match
     Conditions
     Actions
      Countdown Timer - Start TestTimer as a One-shot timer that will expire in 30.00 seconds
      Unit - Create 1 Footman for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      Game - Display to (All players) the text: (String((Elapsed time for (Last started timer))))
      Animation - Play (Last created unit)'s stand animation
      Game - Display to (All players) the text: (String((Elapsed time for (Last started timer))))
      Cinematic - Ping minimap for (All players) at (Center of (Playable map area)) for 1.00 seconds
      Game - Display to (All players) the text: (String((Elapsed time for (Last started timer))))
      Player - Add 1000 to Player 1 (Red) Current gold
      Game - Display to (All players) the text: (String((Elapsed time for (Last started timer))))
    輸入"-test"之後, 我們會發現它印出4個"0"。可見 二句敍述之間沒有任何的時間延遲。(實際上當然還是有一小小小段的執行時間,不過電腦整個處理器的運作方式會被設計成好像不用時間,以便簡化程式的運作,並減少混亂的產生。所以大家就當作是不用時間吧。)

    不過還是有破壞這個原則的東西,W3的GUI Trigger提供了4個延遲函數--Wait(TriggerSleepAction)、Wait game-time(PolledWait)、Wait for Condition、Wait for Sound(WaitForSoundBJ)。其中Wait是較基本的函數,實際運作原理不詳(去問b社吧-_-")。

    Wait會等待一段秒數,但是那個秒數不是遊戲秒,而是和真實時間的「秒」一致。在最快的遊戲速度下,真實的秒比遊戲秒還要慢一些,而遊戲的速度如果調慢,真實秒則可能會變得比遊戲秒快。為了解決這個問題,b社用區域變數和計時器,創造了Wait game-time。它可以相當精確地等待一段遊戲秒,但同時也會對系統資源造成較大的負擔。筆者建議,Wait game-time當然好用,不過只要能夠用Wait寫,還是用它比較省資源。最後兩個函數Wait for Condition和Wait for Sound恰如其義,就是等待直到一個條件符合和等待直到一段音效結束。

    4個時間延遲函數都是有延遲的,最多可多延遲0.2xx遊戲秒左右。即使我寫Wait 0.0 seconds,電腦還是會等待0.0x~0.2x遊戲秒左右(但Wait 0.0 game-time seconds不會做任何等待)。如果我要等待的時間很短,例如0.3秒以下,那麼不建議用Wait,因為0.2x秒的誤差在這種情況下是很嚴重的!
  • 觸發間的互動
    最基本的觸發是一發生什麼事情就做什麼,跟以前發生過什麼事情無關,所以如果你的觸發彼此間是獨立無關聯的,那就不需要理會這個問題。
    但有些觸發必須要某些條件成立才能正常作用,而條件的完成又得依靠其他觸發的執行結果,此時就要注意這個問題。

    簡單的方法是在你的觸發中加入條件來檢查,這用在觸發結構簡單的地圖很不錯,但每個觸發的執行結果不盡相同,要加入的條件種類就五花八門了,甚至有些很難用條件來控制,所以下面介紹幾個指令。

    在一個觸發中加入一個行動,然後你可以在「Trigger(觸發)」類中找到以下幾個指令幫助你控制觸發的執行:
    *Trigger - Turn on
    *Trigger - Turn off
    *Trigger - Run (checking conditions)
    *Trigger - Run (ignoring conditions)

    前兩個一看就知道作用是相對的,這兩個指令是控制觸發的開啟和關閉。

    當你正在編輯某個觸發時,可以在觸發編輯器按鈕列的下方找到「啟用(Enabled)」和「初始值開啟(Initially On)」這兩個核取方塊。前者是設定此觸發是否准許被執行,後者決定在遊戲剛開始時是否開啟這個觸發,和第一個選項不同的是可以在遊戲中使用觸發來切換開關,而第一個選項選了後在遊戲中無法更改。

    一定有人會問:「如果把一個觸發停用,它就永遠不會執行。那我寫那個觸發做有什麼意義?」。基本上這個功能是為了測試方便,有時你可能為了測試而必須暫時讓一個觸發不作用,如果你刪了它,後來要用的時候就得重寫;如果你只是把它停用,日後要用的時候,只要再啟用它即可。

    被設定成關閉的觸發在遊戲中不會執行,所以你可以把一些觸發先設為關閉,然後在其他觸發中把他開啟,之後這個觸發就會作用。同樣的,你也可以把已經開啟的觸發關閉,端看你的需要。

    後兩個是執行觸發,不經由事件啟動。第三個是會檢查條件,若不符合就不會執行。第四個則是忽略條件,強制執行觸發。

    前兩個指令是會保持觸發的開關,後兩個則是只執行一次,要如何使用就全看你的需求了。
回复

使用道具 举报

 楼主| 发表于 8-1-2007 07:05 PM | 显示全部楼层
執行順序
假設我隨便寫一段觸發:
Set x = 100
Player - Set Player 1 (Red) Current gold to x

如果有別的觸發也用到x,有沒有可能在Set x = 100之後到Set Player 1 (Red) Current gold to x之前的那段時間內,改變x的值,使得執行Set Player 1 (Red) Current gold to x時,x不再是100?

基本上是不可能的,因為Set x = 100到Set Player 1 (Red) Current gold to x之間的時間是0,所以別的觸發無法介入。

然而,如果我寫的是:
Set x = 100
Wait 5.00 game-time seconds
Player - Set Player 1 (Red) Current gold to x

那麼等待後的x就未必還是100囉。

不過如果我的動作引發別的觸發,那就另當別論了。如下例,想想看電腦的執行順序,以及執行結果?(反白檢視答案)
Trigger 1
 Events
    Time - Elapsed game time is 5.00 seconds ----(1)
 Conditions
 Actions
  Player - Set Player 1 (Red) Current gold to 0 ----(2)
  Set x = 100 ----(3)
  Player - Set Player 1 (Red) Current gold to x ----(4)
  Player - Set Player 2 (Blue) Current gold to x ----(7)

Trigger 2
 Events
  Player - Player 1 (Red)'s Current gold becomes Greater than or equal to 100.00 ----(5)
 Conditions
 Actions
  Set x = 300 ----(6)

-->所以最後玩者1黃金100,玩者2黃金300
Trigger - Run
這個函數允許一個觸發呼叫另外一個觸發,它又分成Checking Conditions(檢查條件)和Ignoring Conditions(忽略條件)兩種,前者會檢查被呼叫的觸發的條件,全部符合才執行它;後者則否。這是一個很好用的觸發,其中最常見的功能是可以把類似的動作放在一條觸發裡,然後用其它觸發呼叫它,如此便能減少版面,而且如果日後要做調整,只要調整一遍就夠了。例如:
Create Hero
 Events
  Time - Elapsed game time is 10.00 seconds
 Conditions
 Actions
  Unit - Create 1 Archmage for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (ignoring conditions)
  Unit - Create 1 Paladin for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (ignoring conditions)
  Unit - Create 1 Mountain King for Player 3 (Teal) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (ignoring conditions)
  Unit - Create 1 Blood Mage for Player 4 (Purple) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (ignoring conditions)

Create Hero Sub
 Events
 Conditions
 Actions
  Unit - Set life of (Last created unit) to 50.00%
  Unit - Set mana of (Last created unit) to 50.00%
  Unit - Add Blink to (Last created unit)
  Camera - Pan camera for (Owner of (Last created unit)) to (Center of (Playable map area)) over 1.00 seconds
  Cinematic - Ping minimap for (Player group((Owner of (Last created unit)))) at (Center of (Playable map area)) for 1.00 seconds

像這樣就能用Trigger - Run Create Hero Sub <gen> (ignoring conditions)取代原來的4列敍述,而且日後要修改的話,只要修改Create Hero Sub中的內容,而不用在Create Hero那個觸發改好幾遍。

checking conditions也類似:
Create Hero
 Events
  Time - Elapsed game time is 10.00 seconds
 Conditions
 Actions
  Unit - Create 1 Archmage for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (checking conditions)
  Unit - Create 1 Paladin for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (checking conditions)
  Unit - Create 1 Mountain King for Player 3 (Teal) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (checking conditions)
  Unit - Create 1 Blood Mage for Player 4 (Purple) at (Center of (Playable map area)) facing Default building facing degrees
  Trigger - Run Create Hero Sub <gen> (checking conditions)

Create Hero Sub
 Events
 Conditions
  (Percentage life of (Last created unit)) Greater than 50.00
 Actions
  Unit - Set life of (Last created unit) to 50.00%
  Unit - Set mana of (Last created unit) to 50.00%
  Unit - Add Blink to (Last created unit)
  Camera - Pan camera for (Owner of (Last created unit)) to (Center of (Playable map area)) over 1.00 seconds
  Cinematic - Ping minimap for (Player group((Owner of (Last created unit)))) at (Center of (Playable map area)) for 1.00 seconds

由於checking conditions的函數比ignoring conditions函數的程式碼多(即使被呼叫的觸發根本沒有設條件),所以沒有必要的話(觸發沒有條件),盡量少用checking conditions,畢竟對沒有條件的觸發再做一次檢查是浪費資源的行為。

當然這也會有一些影響執行順序之處,不過不會太複雜。想想看,以下範例電腦的執行順序為?(反白檢視答案)
Test 1
 Events
  Unit - A unit Dies ----(1)
 Conditions
 Actions
  Set target = (Killing unit) ----(2)
  Trigger - Run Test 2 <gen> (ignoring conditions) ----(3)
  Set target = (Random unit from (Units within 512.00 of (Position of (Killing unit)))) ----(7)
  Trigger - Run Test 2 <gen> (ignoring conditions) ----(8)

Test 2
 Events
 Conditions
 Actions
  Animation - Play target's death animation ----(4) ----(9)
  Unit - Set mana of target to 0.00 ----(5) ----(10)
  Unit - Remove Positive buffs from target ----(6) ----(11)

如果是這樣呢?(反白檢視執行順序)
Test 1
 Events
  Unit - A unit Dies ----(1)
 Conditions
 Actions
  Set target = (Killing unit) ----(2)
  Trigger - Run Test 2 <gen> (ignoring conditions) ----(3)
  Set target = (Random unit from (Units within 512.00 of (Position of (Killing unit)))) ----(6)
  Trigger - Run Test 2 <gen> (ignoring conditions) ----(7)

Test 2
 Events
 Conditions
 Actions
  Animation - Play target's death animation ----(4) ----(8)
  Wait 2.00 game-time seconds ----(5) ----(9)
  Unit - Set mana of target to 0.00 ----(10.a) ----(10.b) (兩者先後不定,看哪個Wait延遲較少)

-->如果沒別的觸發干擾,執行到10.a和10.b的時候,target值都是後來指定的那個 部隊,所以最後只有一個部隊的法力會歸零。

呼叫觸發,可以產生另外一個獨立的執行體系,如上例可讓兩個Wait同步等待,而如果是這樣,就會先等完一個再等一個:
Test 1
 Events
  Unit - A unit Dies ----(1)
 Conditions
 Actions
  Set target = (Killing unit) ----(2)
  Trigger - Run Test 2 <gen> (ignoring conditions) ----(3)
  Animation - Play target's death animation ----(4)
  Wait 2.00 game-time seconds ----(5)
  Unit - Set mana of target to 0.00 ----(6)
  Set target = (Random unit from (Units within 512.00 of (Position of (Killing unit)))) ----(7)
  Animation - Play target's death animation ----(8)
  Wait 2.00 game-time seconds ----(9)
  Unit - Set mana of target to 0.00 ----(10)

雖然前者的同步寫法有造成變數錯亂的問題,但是在JASS技術中,可以用區域變數解決此問題(請參見JASS教學)。因此開新觸發成了很好的同步設定工具。 Trigger - Add New Event
這個函數也是很好用的東西,它允許我在遊戲中把新的事件加入到觸發中,而且可以選擇變數,例如:
Init
 Events
  Map initialization
 Conditions
 Actions
  Unit Group - Pick every unit in (Units owned by Player 1 (Red) of type Siege Engine) and do (Actions)
   Loop - Actions
    Trigger - Add to Kill <gen> the event (Unit - A unit comes within 128.00 of (Picked unit))

Kill
 Events
 Conditions
 Actions
  Unit - Explode (Triggering unit)

不知道讀者是否能夠理解。這是一個類似電流急急棒的觸發,[Init]觸發會在一開始執行,並且把玩者一的所有坦克加入到[Kill]觸發的事件裡。所以,任何 部隊碰到前面設定過的玩者一的坦克就會炸開(當然,玩者一在遊戲中如果再生坦克,由於它沒有被加到觸發裡,部隊碰到它就不會爆炸了)。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

 

ADVERTISEMENT



ADVERTISEMENT



ADVERTISEMENT

ADVERTISEMENT


版权所有 © 1996-2023 Cari Internet Sdn Bhd (483575-W)|IPSERVERONE 提供云主机|广告刊登|关于我们|私隐权|免控|投诉|联络|脸书|佳礼资讯网

GMT+8, 29-10-2024 04:36 AM , Processed in 0.112300 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表