David Gaider - 変数の設定

変数を設定し、取り出すことは、スクリプト作成において最も行われる行為の1つでしょう。変数の設定と取り出しを用いて、ほとんどのイベントが発生しているかどうかを決定したり、異なったストーリー の状態の変更や記録をすることができます。


変数を設定する時に最も使用される関数は、以下のとおりでしょう。


// void SetLocalInt(object oObject, string sVarName, int nValue)
SetLocalInt(OBJECT_SELF, "VARIABLE1", 1);

この関数は、 ローカル整数を設定します。ローカルに設定するとはどういう意味でしょうか?それは、指定しているoObjectに整数が関係付けられ、保管されるという意味です。(物理的には保管されませんが、この方法だと整数を簡単に参照できます。)


覚えておくべき重要な点は、以下の3つです。


  1. oObjectは有効なオブジェクトである必要があります。SetLocalInt関数の頭の部分がvoidになっているように、返されるオブジェクトが頭の部分にある多くの関数が見られます。これは、それらの関数がそのタイプのオブジェクトを返すということを意味します。
    どんなオブジェクトに対しても整数を関係付けることができます。会話の中でGetPCSpeaker()関数を使用すると、現在NPCと話しているPCがオブジェクトして返されるでしょう。GetModule()関数を使用して、モジュール自身に整数を保管することができます。OBJECT_SELFを使用して、現在のスクリプトを実行しているオブジェクト上の整数を参照できます。
    変数は、そのオブジェクトにとって特有のものになるということも重要です。モジュール上に "VARIABLE1" という変数名で1という値を保管する場合、 その変数は、そのモジュールにとって特有の変数となります。例えばPCといったような異なるオブジェクトに "VARIABLE1" を持たせることはできますが、それは全く違った変数になります。
  2. sVarName は、変数に与える名前です。与える変数名がそのモジュールにとって特有の名前であることを確認して下さい。変数名は全ての文字列のように、 ダブルクォーテーションで囲む必要があります。(上の"VARIABLE1"がその例) 変数名は大文字小文字を区別しません。
  3. nValue は、変数に保管する情報です。この関数では整数を設定しようとしているので、1, 15 または 320といった数字(少数部分なし)である必要があります。モジュールにタイプの異なった情報を保管したければ、異なった関数を使用する必要があります。
// 浮動小数(少数部分がある数字)を保管します。
// void SetLocalFloat(object oObject, string sVarName, float fValue);
SetLocalFloat(OBJECT_SELF, "nw_some_key", 12.0f);
// 文字列(文章、単語、オブジェクトの名前など)を保管します。
// 変数名のようにクォーテーションで囲む必要があります。
// void SetLocalString(object oObject, string sVarName, string sValue);
SetLocalString(OBJECT_SELF, "nw_some_key", "some string");
// void SetLocalLocation(object oObject, string sVarName, location lValue);
// ロケーションを保管します。
SetLocalLocation(OBJECT_SELF, "nw_some_key", GetLocation(OBJECT_SELF));
// void SetLocalObject(object oObject, string sVarName, object oValue);
// オブジェクトデータ(配置可能オブジェクト、所有アイテム、クリーチャーなど)を保管します。
SetLocalObject(OBJECT_SELF, "nw_some_key", OBJECT_SELF); 
変数はどのように使うのでしょうか?

一度変数をあるオブジェクトに設定すると、それは置き換えらえれり、または破棄されるまで保持されます。別のスクリプト(または同じスクリプト)の他の場所においても、その変数を呼び出したり、情報を保管し直したりすることができます。


一度設定した整数データを呼び出したい場合には、以下のようになるでしょう。

// int GetLocalInt(object oObject, string sVarName);

これは、先ほど変数を設定する時に使用した関数から実際のデータ値を指定することを除くと、全く同じ関数です。


void型の関数ではないことに注意してください。この関数は実際の情報として整数値を返します。この関数を単独で使用することはないということです。例えば、以下のようにあらかじめ定義されたintデータを設定する時に使用します。

int nValue = GetLocalInt(OBJECT_SELF, "VARIABLE1");

これは、OBJECT_SELF内の変数"VARIABLE1"に設定された値と同じ値を持った、nValueという新しい変数を設定したということを意味します。


まだ理解しにくいですか? 例を挙げましょう。

変数を使用する方法の1つの良い例は、プロット(ここではクエストとします。)の進行を追跡することです。そこで、"STORY"という変数を用意して、プレイヤーがクエストを受けた時に変数を1に設定し、プレイヤーがクエストを完了したときに変数を2に設定することにします。


プレイヤーがクエストを受けました。

プレイヤーがクエストを受ける会話ノードの「テキストによる処理」に、PC上の"STORY"変数の値を1に設定するスクリプトを作成します。

void main()
{
     SetLocalInt(GetPCSpeaker(), "STORY", 1);
}
プレイヤーがクエストを完了しました。

プレイヤーは、NPCが望んだことをやり遂げて戻ってきました。NPCはプレイヤーを褒め称え、PC上の"STORY"変数を2に設定します。


void main()
{
     SetLocalInt(GetPCSpeaker(), "STORY", 2);
}
プレイヤーがクエストを受けたかどうか、クエストを完了したかどうかを、どのようにすれば知ることができるのでしょうか?

そのためには、会話の該当箇所においてそれぞれの条件に対する新しいノードを作成する必要があります。コンピュータは、先頭のノードから処理を開始して、「テキスト表示の条件」に書かれているスクリプトをチェックします。そして、その戻り値がTRUEである場合、そのテキストを表示します。(何もスクリプトがない場合には、自動的にTRUEと判断されます。)TRUEでない場合は、続けて次のノードをチェックします。


よって、このクエストにおいては、以下のように逆順でノードを並べる必要があります。

  1. (クエストを完了した) "クエストを成し遂げたことに感謝します。"
  2. (クエストを既に受けている) "クエストは完了しましたか?"
  3. (クエストを受けてもなく、完了してもない) "こんにちは!"

そうすると、1.の会話の表示させるために、PC上の"STORY"変数の値が2である場合にTRUEを返すスクリプトを作成する必要がありますよね? また、2.の会話を表示させるためには、"STORY"変数の値が1である場合にTRUEを返すスクリプトが必要になります。3.の会話を表示させるためのスクリプトは必要ありません。なぜなら、1.と2.両方のスクリプトがFALSEを返す場合は、クエストを受けてもいなく、完了してもいないからです。


クエストは完了しましたか?


int StartingConditional()
{
     int nDone = GetLocalInt(GetPCSpeaker(), "STORY") == 2;
     return nDone;
}

クエストを受けましたか?

int StartingConditional()
{
     int nAccept = GetLocalInt(GetPCSpeaker(), "STORY") == 1;
     return nAccept;
}
よって、まとめると以下のようになります。

  1. (「テキスト表示の条件」に設定する最初のスクリプト) "クエストを成し遂げたことに感謝します。"
  2. (「テキスト表示の条件」に設定する2番目のスクリプト) "クエストは完了しましたか?"
  3. (スクリプトなし) "こんにちは!"
上記のスクリプトにおいて、NPCは1人のPCにだけクエストを与えたいとします。

そのためには、PC上の"STORY"変数を1に設定する時に、OBJECT_SELF(NPC)上の"PLOT_GIVEN"という変数を1に設定するというのはどうでしょうか?


それならば、以下のように3.の会話から2つの会話を分岐させる必要があります。(なぜなら、"STORY"変数を持っていない別のPCがぶらりと歩いてきて、NPCに話しかけることもあるからです。)


|
|
--> (「テキスト表示の条件」に設定するスクリプト。OBJECT_SELF上の"PLOT_GIVEN"変数が1である場合にTRUEを返す。) "ごめんなさい。今日はあなたに依頼する仕事はありません。"
|
|
--> (スクリプトなし) "私の依頼を受けてくれませんか?"

非常に簡単なクエストの会話例

ルートの下にノードを並べる時には、実際の会話の逆順に並べなければならないということを憶えておいてください。


以下に、それぞれのノードに必要なスクリプトを示します。


#1 - PC上の"Job"変数の値が4である場合にTRUEを返すスクリプトを、「テキスト表示の条件」に設定します。

int StartingConditional()
{
     int nJob = GetLocalInt(GetPCSpeaker(), "Job") == 4;
     return nJob;
}

#2 - PC上の"Job"変数の値が3(#3で設定されます。)である場合にTRUEを返すスクリプトを「テキスト表示の条件」に設定します。PCが仕事を完了している場合に表示する会話を作成し、NPCがPCに報酬を与え"Job"変数の値を4(これ以上仕事はないということを示す値)に設定するスクリプトを、 「テキストによる処理」に設定します。

void main()
{
     SetLocalInt(GetPCSpeaker(), "Job", 4);
}

#3 - PC上の"Job"変数の値が2(#4で設定されます。)である場合にTRUEを返すスクリプトを「テキスト表示の条件」に設定します。PCが仕事を完了している場合に表示する会話を作成し、NPCがPCに報酬を与え、"Job"変数の値を3に設定するスクリプトを、 「テキストによる処理」に設定します。NPCは次の仕事を依頼します。


#4 - PC上の"Job"変数の値が1(#5で設定されます。)である場合にTRUEを返すスクリプトを「テキスト表示の条件」に設定します。PCが仕事を完了している場合に表示する会話を作成し、NPCがPCに報酬を与え、"Job"変数の値を2に設定するスクリプトを、 「テキストによる処理」に設定します。NPCは次の仕事を依頼します。


#5 - PC上の"TalkedToJoe"変数の値が1(#6で設定されます。)である場合にTRUEを返すスクリプトを「テキスト表示の条件 」に設定します。PCが最初の仕事を受けた場合に表示する会話を作成し、PC上の"Job"変数を1に設定するスクリプトを「テキストによる処理」に設定します。


#6 - 「テキスト表示の条件」にはスクリプトを設定しません。(上記のスクリプトが全てFALSEを返す場合、それはPCがNPCに初めて話しかけたということを意味するからです。)PC上の"TalkedToJoe"変数の値を1に設定するスクリプトを、 「テキストによる処理」に設定します。


これまでに書いたことは、基本的な変数の設定と取り出しに関することです。文字列やオブジェクトデータ、そして他の種類のデータを扱う場合は、少し複雑になります。しかし、一度整数を扱うことに慣れれば、他の種類についても幾分か容易に理解することができると思います。このチュートリアルが、あなたにとってのスクリプト作成のきっかけになれば幸いです。




 author: David Gaider, editor: Charles Feduke, JP team: katsu794
 Send comments on this topic.