GTA SA Modification Center > Pawn > Basics

Basics

Files

Pawnでは .pwn と .amx の二種類のファイルを扱います。
.pwn はソース、スクリプトを記述するファイルです。主にこちらを編集します。
.amx はスクリプト、Pawnコンパイラによってコンピュータが読みやすい形になったスクリプトです。

なぜ、 .pwn と .amx が必要かというと、それは無駄をなくすためです。
.pwn は人間にとって読みやすいのですが、無駄が多く、コンピュータが
実行するときはそれらをいちいち解析していかなくてはなりません。
.amx は人間には読めない形になっていますが、無駄が排され、
コンピュータは苦労せず読む事ができます。

この .pwn から .amx に変換する作業をコンパイルといいます。
コンパイルをするのにはいちいち解析するため時間がかかりますが、
実行時に最高の状態のものを実行する事ができます。

.pwn や .amx 以外にも .inc というファイルを見つける事ができるかもしれませんが、
これはインクルードファイルといい、便利な関数やよく使う関数をここに書いておいて、
コンパイルする際に読み出して使うものです。
ソースファイルをすっきりさせる事ができますし、再配布も簡単です。

Sentence

Pawnの文法はCととてもよく似ています。
一つの文には必ず一つの処理を記述し、文末には ; (セミコロン)をつけます。
x = 23;
y = 13;
z = 42;
また、セミコロンで文末を判断するため、一つの文が複数の行にわたっていてもかまいません。
x[4][4] = {
 {0, 1, 1, 0},
 {1, 0, 0, 1},
 {1, 0, 0, 1},
 {0, 1, 1, 0}
};

Comment

Cと同様にPawnでもコメントをつけることができます。
これはスクリプトの可読性を高める効果があるので、特に長いスクリプトではつけておく事をおススメします。
// を使うとそれ以降、行末までをコメントアウトできます。
x = 25; //xに25を代入
/* ~ */ を使うとその範囲内をコメントアウトできます。
複数の行にわたる事も、文の途中に書くこともできます。
/*
 Pawn Script
  by someone
  2007.7.6
*/

Variable

Pawnでも当然変数を使う事ができます。
変数を定義するときは new を使います。
同時に初期値を設定する事もできます。
new x;
new a = 10;
変数にはスコープ、有効範囲があり、関数の中などで定義したものは関数が終了したとき、
スクリプトで定義したものはスクリプトが終了したときに破棄されます。
new x; //スクリプトが終了するまで残る
myfunc()
{
 new y = 7; //関数が終了するまで残る
 for(new z = 0; z < y; z++) //forが終わるときまで残る
 {
  new w; //forの1ループが終わるときまで残る
  w = 10;
  printf("%d", w);
  //ここでwが破棄される
 }
 //ここでzが破棄される
 y++;
 printf("%d", y);
 //ここでyが破棄される
}
変数には型があります。指定しなければ整数になります。
Cほどは多くありませんが、明示的に指定する必要があります。
例えば Float は小数を表します。
new x = 10; //OK
new y = 52.3; //Error!!
new Float:z = 31.7; //OK

Array

配列を使うと、データの管理が楽になります。(ってか配列使わないとヤバス)
配列は 変数名[数] の形で定義します。[]を複数つけて多次元配列を表現する事もできます。
値を参照するときは 変数名[要素番号] の形でします。
要素番号は 0~定義したときの数-1 の範囲の整数です。
new a[6]; //6つの要素を持つ配列
new b[6] = {5, 2, 7, 2, 3, 9}; //初期値も設定できる
new c[4][4]; //2次元配列
printf("%d", b[2]); //7が出力される
配列の応用で文字列を表現する事もできます。
要素番号をつけずに変数として渡すとポインタ(変数のアドレス)が返ります。
文字列を扱う関数でよく使われています。
new str[16] = "This is a pen."; //最大16文字の文字列
print(str); //strのポインタを渡してstrの内容を出力

Structure

構造体は、配列と似ていて一つの変数にいくつもの値を格納できますが、
数が決まっていて一つ一つに名前・型を指定することができます。
enum で定義します。要素同士は , 区切り、 {} で囲い ; はいりません。
enum PROFILE
{
NAME[16],
AGE,
SEX,
Float:MARKS
}
変数を定義するときは配列のような形で定義します。
new students[30][PROFILE] =
{
 {"Alice", 14, 1, 73.6},
 {"Andrew", 16, 0, 52.7},
 {"Barbara", 16, 1, 68.3},
 {"Bryan", 15, 0, 85.2},
     :
     :
 {"William", 14, 0, 74.1}
};
構造体の内容を読み出すときも配列のように読み出します。
for(new i = 0; i < 30; i++)
{
 printf("%16s AGE:%4d SEX:%6s MARK:%f", students[i][NAME], students[i][AGE], students[i][SEX] ? "FEMALE" : "MALE", students[i][MARKS]);
}

Function

関数は 関数名(引数){処理} の形で記述します。
引数は渡される形を指定しないといけません。
引数同士は , で区切ります。 引数=値 を記述すると省略が可能です。
myfunc(num, name[] = "NONE", age = 0, sex = 0, Float:marks = 50.0)
{
 students[num][NAME] = name;
 students[num][AGE] = age;
 students[num][SEX] = sex;
 students[num][MARKS] = marks;
}

myfunc(0, "Alice", 12, 1, 78.4); //0番をAlice,12,1,78.4に設定
myfunc(1); //1番をNONE,0,0,50.0に設定
return を使うと戻り値を設定できます。
その瞬間関数が終了するので気をつけてください。
getage(num)
{
 return students[num][AGE];
}

x = getage(0);
引数は通常、呼び出したときに指定したものをコピーしたものを関数内で使い、
関数が終われば破棄しますが、& (アンパサンド)を使うと元の変数を参照できます。
getage(num, age)
{
 age = students[num][AGE]; //こうしても元の変数は変わらない
}

getage(0, x); //意味無し


getsex(num, &sex)
{
 sex = students[num][SEX]; //元の変数も変わる
}

getsex(0, x); //意味あり
特殊な引数を指定すると引数を無限に受け取れます。
setmarks(start, {Float,_}:...)
{
 for(new i = 0; i < numargs() - 1; i++)
 {
  students[i + start][MARKS] = getarg(i + 1);
 }
}

setmarks(0, 52.4, 84,2, 89.3, 74.9, 73.0); //0番から順番に25.4, 84.2... と設定していく