找回密碼
 註冊
[日本手機遊戲APPS下載] 手機遊戲專區 熱門短片

型男索女 
查看: 4604|回復: 1

write amxx

[複製鏈接]
發表於 4-9-2011 20:18:14 | 顯示全部樓層 |閱讀模式
AMXx 插件編寫指南11. 介紹Pawn 語言是一種跨平台的腳本語言. 我們常看到兩種類型的語言, 一種是"編譯"語言, 例如: C 和 C++. 一種是"解釋"語言, 像 VB Script.
AMX Pawn 語言是兩者的混合體: 將腳本編譯成二進制文件, 並由 AMXx 來解釋它.

當然, 在編寫你的腳本之前, 你必須先知道幾種結構.
第一是 "變量".
變量是一個符號或者標記用來保存數據. 例如:變量 "a" 能夠保存數字 "2", "16", "0", 等等. 變量由程序創建一個空間讓你保存數據. 你必須在使用它們之前先定義你的變量. 變量用 = 號來賦值:


new a,b,c,d

a=5
b=16
c=0
d=500


第二是 "函數". 函數是一個符號或者標記, 當你調用它的時候, 它就會執行一些操作. 這意味著當你調用它們的時候, 它們將會處理你提供給它們的數據.
函數有幾種類型, 但是調用的方法還是類似的. 例如: "show" 函數輸出幾個數據到屏幕上:


show(56) //激活 "show" 函數, 並將值 56 傳遞給它
show() //激活 "show" 函數但是不傳遞數據給它
show(a) //激活 "show" 函數, 並將變量 a 的值傳遞給它


注意, 任何以 "//" 開頭的文字都屬於註釋.
你所傳遞給函數的每一個數據都稱之為 "參數". 一個函數可以有幾個參數, 而你必須保證傳遞給函數的參數數據必須正確.
如果參數是兩個數字, 你就不能傳遞一個單詞.
函數也可以返回數據, 像這樣:


new b
b = add(5, 7)


在例子中, 假設 "add" 是一個將兩個數字相加並返回和的函數, 變量 "b" 的值將為 12.

第三個概念是 "代碼塊", 也就是結構化. 你可以將一段代碼用 { 和 } 符號合併成一個代碼塊.
例如:


{
here
is
some
code
}

通常我們習慣盡可能地使用代碼塊, 並將代碼塊裡面的代碼縮進.

以上是介紹 Pawn 語言的背景.


2. Pawn 語言基礎目錄:
變量
數組
字符串
函數
表達式與操作
條件
循環
二維數組
編譯器指令
結束語
1. 變量

Pawn 語言是一種可嵌入的, 幾乎無類型的, 容易使用的虛擬機腳本語言.
AMX Mod X 使用 Pawn 語言傳遞函數到 Half-Life 引擎, 使用 Pawn 虛擬機和 Metamod (Pawn 是用 C 寫的, Metamod 是用 C++ 寫的).
當你寫完腳本之後, 必須用 AMX Mod X 提供的編譯器編譯成二進制文件. AMX Mod X 小組在每一個版本都有隨之分發.

用 Pawn 語言來編寫腳本是很容易的, 並且不需要使用其他語言用不到的概念, 例如 指針, 向量, 結構, 類, 流, 等等.
Pawn 語言只有三種數據類型. 默認的數據類型是整數. 一個變量名不能大於 19 個字符, 而且必須用字母開頭.
它可以包含 A-Z, a-z, 0-9, 還有下劃線 ("_").
變量名對大小些敏感, 例如 "myvar", "MyVaR", 和 "MYVAR" 是三個不同的變量. 定義一個變量可以是用 "new" 關鍵字:


new a //定義一個變量 "a"
new b=5 //定義一個變量 "b" 並賦值為 5.
new c=5.0 //這樣不合法, 技術上, 5.0並不是一個整數!
new d="hello" //這樣不合法, "hello" 不是一個數字.

//你也可以在一行裡定義多個變量:
new e,f,g,h
new x=7, y=3


你也可以用 "Float" 關鍵字定義一個浮點數, 即帶有小數部分的整數. 定義方法如下:


new Float:a //定義一個浮點數變量 "a"
new Float:b=5.3 //定義一個浮點數變量 "b" 並賦值為 5.3.
new Float:c=5 // 這樣雖然合法, 但是編譯器會出現一個警告信息.
new Float:d="hello" //這樣不合法, "hello" 不是一個浮點數.

你也可以這樣:
//float(n) 是一個將整數轉換為浮點數的函數.
new Float:var = float(5)
new Float:var2 = 5.0
new Float:var3 = 1.0*5
new var4 = floatround(5.0)
//注意: floatround(n) 是一個將浮點數轉換為近似整數的函數.


注意 - 空格的多少並沒有什麼關係, 編譯器會處理. 但是也不能太離譜, 例如: "new var = 5" 和 "new var=5" 是相同的, 但是 "newvar=5" 就完全錯了.

最後一個數據類型是邏輯值. 只有 "真" 和 "假" 兩個值.


new bool:IsItOn //定義一個邏輯值 "IsItOn", 默認為 "假".
new bool:xyz=true //定義一個邏輯值 "xyz" 並賦值為 "真".



2. 數組

Pawn 的其中一個功能: 數組. 數組是一組數據的集合. 這樣你可以在一個變量裡儲存多個數據!
數組的定義方法和普通變量一樣, 並且類型也和普通一樣. 它能包含多個數據. 用括號 [] 來定義數組的元素數量, 例如:


//定義一個 32 個元素的數組 "Players"
new Players[32]
//你可以使用數組中的任何一個元素, 每個數組的元素的位置都是由 0 到 n-1
//每一個數組的元素的位置都是從 0 開始的.

//為數組的第一個元素賦值 5
Players[0] = 5
//令數組的第二個元素的值為第一個元素的值
Players[1] = Players[0]
//以下是不合法的!
//雖然數組有 32 個元素, 但是元素的位置是 0 到 31.
//這樣做會出現 AMX_ERR_BOUNDS 錯誤.
//或者, 無法編譯.
Players[32] = 15
//這樣更不合法了.
Players[-1] = 6
new a = 3
//以下這樣做也是一樣不合法.
//a 必須是一個常數, 在這裡 a 是一個變量:
new BadArray[a]
const b = 3
new GoodArray
//你也可以使用 編譯器指令 (見最後一章)

#define ARRAY_SIZE 3
new Array[ARRAY_SIZE]


數組定義時也可以賦值, 像這樣:


new Numbers[4] = {0,1,2,3}
//注意: 賦值時元素的數量必須完全吻合.


你也可以使用其他數據類型的數組:


//浮點數數組:
new Float:Numbers[4] = {0.0, 1.2, 2.4, 3.8}
//邏輯值數組. 以下將初始值都賦值為 true 了.
new bool:playerHasGun[32] = true



3. 字符串

你也許注意到我們好像沒說過一個重要的數據類型 - 字符 (字母和符號). 它們被稱為 "字符串", 在 Pawn 語言裡, 他們只是一些數字!
一個字符串是一個 ASCII 字符的數組. 例如:


//定義一個字符串 "myString" 包含字符 "Hello".
//它將有 6 個元素, 因為它包含了 5 個字符.
//最後一個元素保留為數字 0, 這樣 Pawn 引擎就可以知道這是一個字符串.
new myString[] = "Hello"

//注意: 任何在 /* 和 */ 之間的文字都屬於註釋. 你不能在 /* */ 裡包含另一個 /* */.
/* 以下做法的結果和上面一樣, 但是, 複雜的多, 所以我們不推薦你這樣做.*/
原理是 "Hello" 的每個字符串保存在 myString 數組中.
new myString[6]
myString[0] = "H"
myString[1] = "e"
myString[2] = "l"
myString[3] = "l"
myString[4] = "o"
myString[5] = 0

/*你不能像下面這樣做! 這樣可能會導致溢出.*/
new myString[6]
myString = "Hello" //INVALID!
myString[0] = "Hello" //INVALID!
//如果你想添加一個字符串, 你可以這樣做:
new goodString[6]
copy(goodString, 6, "Hello")

//copy 函數可參見 點通 AMXx 常用函數漢化小組 漢化的函數文檔.:
copy(destination[], length, source[])

//最後, 為了證明字符串只是一個包含數字的數組, 請看以下例子:
new weird[6]
weird[0] = 68
weird[1] = 65
weird[2] = 73
weird[3] = 86
weird[4] = 68
weird[5] = 0
//這將定義變量 "weird" 並賦值為字符串 "DAVID".
//如果想知道字母和符號是怎樣轉換為數字的話, 可訪問 www.asctiitable.com



4. 函數

Pawn 語言允許你定義自己的函數. 函數可以讓你的代碼重用.
注意: 所有函數必須返回值. 你可以使用 "return" 命令, 用來中止函數並返回值.
例如:


//這個函數沒有任何參數, 並且返回 1.
//當使用的時候, 它執行了一個實際上不存在的函數 "print".
//這只是作為例子.
show()
{
print("Hello!")

return 1 //End, return 1
}

//使用方法:
show()


你也可以定義需要參數的函數.


//以下定義了一個函數 "add_two_numbers", 將兩個數字相加.
add_two_numbers(first, second)
{
new sum = first + second

return sum //Return the sum
}
//你可以這樣使用它:

new a,b
a = 5
a = 12
new c = add_two_numbers(a,b)
//c 將等於 5 +12 = 17.


在函數的參數中, 你可以使用任何數據類型. 參數是通過 "傳遞" 機制而發送到函數的.
你可以將數據或者變量傳遞給函數.


//下面定義了一個新函數 "add_two_floats"
//可以將兩個浮點數相加.
Float:add_two_floats(Float:first, Float:second)
{
new Float:sum = first + second

return sum
}

new Float:a
new Float:b
a = 5.0
b = 6.3
new Float:c
c = add_two_floats( a+b )
//c 將等於 5.0 + 6.3 = 11.3

//你甚至可以傳遞數組! 你不需要指定數組的大小.
//如果你指定了, 你就必須確定你傳遞到函數的數組的大小和類型與你所定義的一致.
add_two_from_array(array[], a, b)
{
new first = array[a]
new second = array
new sum = add_two_numbers(first, second) //使用我們先前定義的函數

return sum
}


記住, 數組是使用 "引用傳遞" 機制.
當我們傳遞一個普通的值的時候, 它將先複製到內存中, 然後傳遞給函數, 之後刪除.
但是在傳遞數組時, 由於數組可能非常大, 所以使用 "引用傳遞" 機制.
這意味著如果你在函數里改變了數組的值, 原先的數組也會改變.
例如:


//這個函數將交換數組裡位置 a 和位置 b 的值.
swap_slots(array[], a, b)
{
new temp //注意, 在交換之前你必須先存儲其中一個位置的值作為臨時變量
//否則, 你不能交換兩個數的值! 這是一個很經典的問題了.
//如果你有 a 和 b, 將 b 賦值為 a 然後消除 b 原先的值.
temp = array
array = array[a]
array[a] = temp
}

new myArray[2]
myArray[0] = 5
myArray[1] = 6
swap_slots(myArray, 0, 1)
//myArray[0] 為 6, myArray[1] 為 5

//你可以通過使用 "const" 關鍵字來防止數組的值被改變, 像這樣:
add_two_from_array(const array[], a, b)
{
new first = array[a]
new second = array
new sum = add_two_from_array(first, second)
return sum
}
//注意,當你使用函數的時候, 你可以保證數組不會修改了.

//這個函數將數組作為常量來傳遞. 所以此函數是無法生效的.
bad_function(const array[])
{
array[0] = 0
}



5. 表達式

表達式和數學式子差不多, 都是計算一些數據並返回值.
表達式通常是一些括號表達式的組合, 並通過固定的順序來計算 (從內到外, 先計算括號內的, 然後是乘法, 除法, 加法, 減法, 等等), 像四則混合運算法則一樣.
任何地方都可以使用表達式. 你可以設置變量的值為表達式, 甚至可以傳遞到函數.


//這是一個簡單的表達式. 返回數字 0.
0
//為了更容易看懂, 這樣也是可以的:
(0)


如果一個表達式非 0 或者非假, 它不但返回它的值, 還可以返回真. 否則, 它將返回 0, 也就是假.


//以下是一些數學表達式. 數學符號是:
// + 加
// - 減
// * 乘
// / 除
// % 模運算 (餘數 (5%2 等於 1))
(5+6) //返回 11
((5*6)+3) //返回 33
((((5+3)/2)*4)-9) //返回 5
((5*6) % 7) //返回 2
//其他表達式:
(true) //返回真
(5.0 + 2.3) //返回浮點數 7.3

//還有一些可直接用到變量上的表達式.
new a = 5
new b = 6
//自加符號.
a++ //返回 a+1, 或者 6. 先返回自己的值, 再將自己加 1.
++a //也返回 a+1, 或者 6. 先將自己加 1, 再返回自己的值.


兩者有一個微妙的差別. a++ 先返回自己的值, 再將自己加 1. ++a 先將自己加 1, 再返回自己的值.
可以在條件或循環語句中使用此操作以節省時間.


a-- //返回 4, 先返回自己的值, 再將自己減 1.
--a //返回 4, 先將自己減 1, 再返回自己的值.

//注意: a++ 實質上等於:
a = a + 1
//你也可以這樣寫代碼:
a = a 操作符 y
//操作符 是一個數學運算符的話. 可以精簡成:
a 操作符= x
//請看下面例子:
a += 1 //等同於 a = a + 1
a -= b //等同於 a = a - b
a *= 0 //等同於 a = a * 0
a /= 2 //等同於 a = a / 2.


數學運算符 並不是唯一的操作符. 還有其他操作符可以讓你進行邏輯判斷.


//"與" 操作符: &&. 比較左右兩邊的表達式,
//如果都為真, 則返回真.

//如果兩者都不為真, && 返回假.
(1 && 0) //返回假, 因為 1 返回真, 而 0 返回假.
(1 && 2) //兩邊都為真, 所以返回真.
(true && false) //假
(false && false) //假
(true && true) //真

//另一個重要的操作符 "或": ||. 如果兩邊之中的一邊為真, 則返回真.
(1 || 0) //真, 因為 1 為真.
(1 || 2) //真
(true || true) //真
(false || false) //假
(true || true) //真


還有其他操作符, 但你可能不常用. "位與" 操作返回一個二進制序列是否包含在另一個序列之中.
在技術上的限制, 它在兩個數字的每一個二進制位上都執行 "與 (&&)" 操作.
例如: 如果你有數字 "9", 二進制碼為 "1001". 如果你要知道它是否包含 "8" (1000), 你可以這樣做:


//返回 8, 因為 8 確實是 9 中的一位.
(9 &  
//4 (00100) 並不是 16 (10000) 中的一位, 所以返回 0.
(16 & 4)
//下一個操作符是 "位或": |
//它在兩個數字的每一個二進制位上都執行 "或 (||)" 操作.
//下面將 9 (1001) 與 3 (0011) 比較, 返回 1011, 或者 11.
(9 | 3)


這兩個操作符雖然重要, 但是並不常用. 它們是位移操作符, << 是左位移, >> 是右位移.


//將數字 3 (00011) 的二進制碼向左移動 3 位, 結果為 (11000), 或者 24.
(3 << 3)
//將數字 24 (11000) 的二進制碼向右移動 3 位, 結果為 (00011), 或者 3.
(24 >> 3)


最後一個操作符是 "位非": !. 它將數據做相反操作. 用於數字上的時候, 它將交換數字的二進制碼 (1 變為 0, 0 變為 1).


//返回假
(!true)
//返回真
(!false)
//將 9 (二進制碼 1001) 變為 6 (二進制碼 0110).
(!(9))



6. 條件

條件語句可以讓你在某種情況下執行你所指定的操作.
最重要的條件語句是 "if ... then". If 計算給定的表達式的值為 "真" 或 "假".
如果為真, 則執行代碼塊. 否則, 執行另一個代碼塊. 例如:

這是一個最基本的 if ... then 語句. 第一行檢查表達式是否為真.
在這裡, 如果變量 a 的值為 5, 則執行下面的代碼塊, 將 a 賦值為 6.


if (a == 5)
{
a = 6
}


可是, 如果 a 的值不等於 5 的話呢? 代碼就不會執行.
然而, 你可以讓程序在表達式為假的情況下執行另一個代碼塊. 現在, 如果 a 等於 5, a 將被賦值為 6. 否則, 賦值為 7.


if (a == 5)
{
a = 6
} else {
a = 7
}


在 if () 語句中你可以使用許多不同的操作符. 事實上, 你可以使用任何計算 "真"(非 0) 或 "假"(0) 的表達式.


//如果 a 不等於 5 則返回真
if (a != 5) {
//如果 a 大於 5 則返回真
if (a > 5) {
//如果 a 小於 5 則返回真
if (a < 5) {
//如果 a 大於或等於 5 則返回真
if (a >= 5) {
//如果 a 小於或等於 5 則返回真
if (a <= 5) {
//返回真, 因為 5+6 = 11 非0
if (5+6) {
//如果 a 和 b 都為真則返回真
if (a && b) {
//如果 7.5 大於 c 則返回真
if ( ((5*3)/2) > c) {
//總是返回真
if (true) {
//總是返回假
if (false) {


注意: 數組無法直接比較. 以下的表達式不合法:


my arrayOne[3]
my arrayTwo[3]
if (arrayOne == arrayTwo) {


你必須這樣:
if ((arrayOne[0] == arrayTwo[0]) &&
(arrayOne[1] == arrayTwo[1]) &&
(arrayOne[2] == arrayTwo[2])) {


很明顯, 如果數組很大的話, 表達式將很長. 在後面我們將介紹如何簡單地比較數組或字符串.

if...then 語句可以使用多層表達式判斷, 如以下例子.


//"if...else if" 的示例
if (a == 5) {
//如果 a 等於 5 則執行此段代碼.
} else if (a < 6) {
//如果 a 小於 6 則執行此段代碼.
} else if (a == 7) {
//如果 a 等於 7 則執行此段代碼.
} else {
//如果都不符合以上的條件, 則執行此段代碼.
}


在上面的例子中有一個重要的地方, 就是表達式是按順序來判斷的, 如果其中一個條件為真, 則執行該代碼塊, 並且, if 語句結束, 而不會再判斷下一個表達式.

最後, 介紹另一種類型的條件判斷語句: "switch" 語句, 它允許你判斷某個變量是否為某個值, 但是它不夠 "if...else if" 好用.


//switch 語句示例
switch (a)
{
case 5:
{
//當 a 等於 5 時執行該代碼塊.
}

case 6:
{
//當 a 等於 6 時執行該代碼塊.
}

case 7:
{
//當 a 等於 7 時執行該代碼塊.
}

default:
{
//當 a 不等於以上值時執行該代碼塊.
}
}


注意: switch 語句也和 if 語句類似, 如果其中一個條件為真, 則執行該代碼塊, 並且, switch 語句結束, 而不會再判斷下一個表達式.

循環語句是任何語言都必有的語句. 它允許你在特定的條件下重複執行某段代碼.最常用的循環語句: "for 循環". 它包含一個初始語句, 執行條件, 增量語句.然後不斷地執行代碼直到條件不為真. 例如:說明: 下面提供了一個管理數組的好方法!下一個重要的循環類型是: "while 循環". 它只有一個參數: 條件語句.只要條件為真, 它就執行代碼. 看看上面例子的 while 循環版本. 在 Pawn 語言裡我們還可以定義數組中的數組.我們可以通過它來創建一個數據表格, 第一個 [] 表示行數, 第二個 [] 表示列數. 二維數組像以下這樣定義:請看以下例子.BigArray 的結果將會是這樣: 注意: 剛才的 sum_of_array() 函數還是可以使用! 我們可以這樣做:因為 BigArray[2] 包含另一個一維數組, 包含 {7,8,9}. 下面, 讓我們寫一個二維數組求和函數. 注意, 二維數組也可以保存字符串.StringList 的結果將會是這樣: 在多維數組裡比較字符串也是一樣的: 編譯器指令可以改變你的代碼. 這裡只簡要帶過. 這篇文章簡要地介紹了 Pawn 語言的一些基礎知識. 它包含了 Pawn 語言的方方面面.如果你想瞭解更多, 請訪問: (注意: 這個 pawn-lang.pdf 文件很長, 你只可以作為一個參考. 你可以訪問 AMX Mod X 論壇). 請看下一章來瞭解如何編寫 AMX Mod X 插件! 想自己製作一個插件吧? 首先你必須看過了上面兩章, 而且必須坐在電腦前面, 打開一個文本編輯器(記事本也可以), AMXx 編譯器.如果你想現在就寫一個魔獸插件, 黑客帝國插件, 死亡競賽插件, 那是不可能的事吧.我推薦你使用 AMXX Studio: 作為你的腳本編輯器. 你必須知道怎麼編譯插件. 你可以參見 "編譯插件" 那一章.你也必須知道如何使用插件. 一個 AMX Mod X 可以有四種主要類型的函數. 第一種是 "公共" 函數. 這意味著它在 AMX Mod X 引擎裡公共可見.第二種是 "Native" 函數, 來自 AMX Mod X 核心模塊.第三種是常規用戶函數, 就是你自己定義的函數.第四種是 "Forward" 函數,當某個特殊事件發生時將被觸發 (同時也是一個公共函數).一個 AMX Mod X 插件必須由一個初始化函數開始:試試編譯上面的插件. 它將會非常小 - 因為它沒有什麼代碼.當你載入你的插件後, 在 HLDS 控制台輸入 "amxx plugins", 你可以見到你的插件顯示在裡面. AMX Mod X 提供了一個創建管理員命令的簡單方法. 每個命令都被註冊為控制台命令. 當你註冊一個命令時, 你必須定義 4 個參數: 在控制台輸入的命令, 輸入該命令時執行的函數, 執行該命令的管理員等級, 該命令的簡短介紹.為了演示, 讓我們製作能通過 "amx_hp" 命令更改玩家生命值的插件.我們必須先做兩件事 - 第一, 註冊命令. 第二, 確認我們輸入命令時執行的函數是存在的.第一個新函數是 "register_concmd", 有 4 個參數.第一個參數是玩家在控制台輸入的命令. 第二個參數是處理該命令的公共函數. 第三個參數是使用該命令的玩家管理員等級. 最後一個參數是該命令的說明 (輸入 amx_help 命令時可看到). 下一步, 我們創建了一個公共函數來處理 amx_hp 命令. 注意, 它有 3 個參數. 這些參數保存著使用該命令的玩家的一些數據. - id 是輸入該命令的玩家的索引, level 是使用該命令的管理員等級 (你必須自己檢查玩家的管理員等級), 而 cid 將保存該命令的內部索引.並且, 注意 PLUGIN_HANDLED. 通常我們使用兩個主要的返回值 PLUGIN_CONTINUE 意思是繼續正常操作, 而 PLUGIN_HANDLED 意思是中止下面的操作.兩者之間有微妙但是很重要的區別. 例如, 當綁定一個命令的時候, 你絕對不能返回 PLUGIN_CONTINUE.但如果你綁定到 "say" 命令的時候返回 PLUGIN_HANDLED, 它將不會顯示玩家輸入的文字.你必須小心地使用它們. 重要的事情先來. 我們怎樣知道玩家擁有 ADMIN_SLAY 權限呢? cmd_access() 函數將會檢查一個命令的信息 (用戶, 管理員等級, 索引) 並且確認兩件事情: 用戶是否有權限執行, 命令是否帶有足夠的參數.這裡我們需要 3 個參數, 因為命令看起來是這樣的: amx_hp <目標> <數量>, 命令本身也算做一個參數.如果 cmd_access 函數執行失敗, 我們將立即中止命令.下一部分是: 我們需要獲取兩個參數. "數量" 參數很簡單, 我們只需要將字符串轉換為數字.第二個參數就比較麻煩, 因為我們要用到三種人群上:所以, 整個 amx_hp 插件如下: 服務器參數是例如 "mp_startmoney" 等設置. 你可以在 plugin_init() 過程中註冊你自己的服務器參數. 讓我們自己製作一個 mp_startmoney.(這個插件可能不能用, 只是一個演示). 你可以設置參數為整數, 浮點數, 或者字符串. 你可以修改任何服務器參數. 如果想瞭解更多 AMX Mod X 插件可使用的函數, 你可以查看由 發佈的函數說明文檔. 你也可以訪問 http://www.amxmodx.org/ 提出問題, 或看看其他用戶的使用經驗. 當然, 這個網站是英文的. 你也可以訪問 提出問題, 或看看其他用戶的使用經驗.

http://hi.baidu.com/duanqilong/b ... 54728da61e12bf.html
回復

使用道具 舉報

發表於 7-9-2011 21:58:51 | 顯示全部樓層
系就系好用@@
不過應該冇咩人甘認真去睇

全部一堆字
最尾戈個 先抵diu
回復 支持 反對

使用道具 舉報

您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

小黑屋|Archiver|手機版|Nakuz.com |網站地圖

GMT+8, 4-5-2025 20:40 , Processed in 0.221544 second(s), 12 queries , MemCache On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回復 返回頂部 返回列表