Celowin - パート 7: アイテムのためのスクリプト

前置き


この一連のレッスンの目的は、全くの初心者をプログラミングの世界に誘い、モジュールを作成するためにNWNのスクリプトをどのように使うかを教えることです。初めの 部分のレッスンはとても基本的なものになると思われるので、何かのプログラムを書いたことがある人は飛ばしても構わないでしょう。これらのレッスンの最終目的は、プログラムと聞いただけで身震いするような人々でも学べる場を提供することです。


これらのレッスンをフォーラムに掲示したり、印刷したり、修正を加えることは大いに構いません。しかし、その際には私が作成したということをどこかで触れて下さい。良い悪いを含めて、これらのレッスンについて何かコメントがあれば私に送って下さい。Celowin.


これらのレッスンは、オーロラツールセットをある程度触っている人を想定して書かれています。これらのレッスンにおいて解りにくい部分があるという意見が多数寄せられれば、必要な部分をさらに詳しく説明することも考えています。


今までのレッスンを見逃した人で、興味のある人は、BiowareのスクリプトフォーラムにあるScripting FAQ and Tutorialsを見て下さい。そこに全て置いてあります。[NWN Lexicon's Lyceumにも同様にミラーされていいます。].

 


イントロダクション


私は、「アイテムにスクリプトを割り当てるためにはどうすればいいでしょうか?」という質問を多く受けます。


単純な答えは「できません。」です。しかし、それでは十分な答えではありませんので、詳しく説明させて下さい。どんな理由であっても(私の推測ではキャラクターのエクスポートにおけるバランス調整のため) [そして、パフォーマンスのため]、BioWareはアイテムに直接スクリプトを設定することを禁止しています。しかし、アイテムのためにスクリプトを書くことはできます。そのためには、幾分遠回りな方法を使う必要があります。


アイテムのプロパティを編集するときの「呪文詠唱」オプションの下に、2つの追加選択があります。特殊な機能と特殊な機能:自身のみです。 これらの2つを使って、全ての種類の特殊な機能を追加することができます。「特殊な機能:自身のみ」は、使われるだけのアイテムのためのものです。ただの「特殊な機能」は使用対象が必要なアイテムのために使います。


アイテムにスクリプトを設定できないのであれば、どのようにしてスクリプトを書くのでしょうか?Well, go to Edit > Module Properties > Events tab, そこにはモジュール全体に設定できるスクリプトスロット一覧があります。その中の1つに「OnActivateItem」というのがあります。今回はこのスロットを使って楽しいことをします。アイテムのためのスクリプトを書くためには、以下の4つの関数を理解する必要があります。

  1. GetItemActivated – この関数は使われたアイテムを返します。
  2. GetItemActivatedTarget – アイテムがオブジェクトに対して使われたのであれば、そのオブジェクトを返します。(もちろんクリーチャーもオブジェクトであることを思い出して下さい。)
  3. GetItemActivatedTargetLocation – アイテムが場所に対して使われたのであれば、そのロケーションを返します。アイテムがオブジェクトに対して使われたのであれば、そのオブジェクトのロケーションを返します。
  4. GetItemActivator – アイテムを使ったPCを返します。

これらはとても簡単な説明なので、例をとおしてそれぞれの機能を見てみましょう。


例 1: 欠点のあるヒーリング・アミュレット


PCをヒーリングできるアミュレットを作ってみましょう。しかし、ちょっと面白くするために、完璧なヒーリングをできないようにしてみます。PCが受けたダメージの半分だけしかヒーリングできないようにして、その力を押さえるために、使用できる回数は1日1回に制限したいと思います。


まず、元となるアイテムを作ります。

  1. アイテム・ウィザードを起動します。
  2. アイテムの種類で、「アミュレット」を選択します。
  3. 「割れたアミュレット」という名前にします。
  4. 「魔法関連」をチェックし、アイテムのレベルを 1-5、アイテムの品質を低に設定します。
  5. 次の画面で、その他、装飾品類、アミュレットを選択します。
  6. 最後の画面で、「アイテムのプロパティを起動」をチェックして完了をクリックします。
  7. 「一般」タブで、タグをHEALNECKに変更します。
  8. 「プロパティ」タブで、貸与済みのプロパティを全て削除します。
  9. 「呪文詠唱」、「特殊な機能:自身のみ」を追加します。
  10. 追加したプロパティを選択して、画面下の「プロパティの編集」をクリックします。
  11. 「1日1回まで使用可」を選択して、OKを押します。
  12. テストを楽にするために、「鑑定済み」をチェックします。
  13. OKを押して、アイテムのプロパティ画面を閉じます。

次に、スクリプトを編集するために、編集メニューから「モジュールのプロパティ」を選択して、「イベント」タブを選択し、そして、OnActivateItemスロットに以下のスクリプトを設定します。


// モジュールのOnActivateItemスロットに設定するスクリプト: tm_activate
//
// このスクリプトはモジュール内の特定のアイテムを扱います。
// 現在の特定アイテム: 
// 割れたアミュレット
//
// 作成者: Celowin
// 最終更新日: 7/15/02
//
void main()
{
  // 全体的な初期化:  どのアイテムが使われたかを見つける。
  object oUsed = GetItemActivated();

  // 以下のセクションは、割れたアミュレットのためのスクリプトです。
  // アミュレットは、使用された時にPCのダメージの半分をヒーリングします。
  if (GetTag(oUsed) ==  "HEALNECK")
  {
    // まず、PCを得る。
    object oPC = GetItemActivator();
    
    // PCがどれだけのダメージを受けているかを調べます。ヒーリングするのはその半分です。
    int nDamageTaken = GetMaxHitPoints(oPC)-GetCurrentHitPoints(oPC);
    int nHealing = FloatToInt(IntToFloat(nDamageTaken)/2);
    
    // ヒーリングを実行し、ちょっとした視覚エフェクトを適用します。
    effect eHeal = EffectHeal(nHealing);
    ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oPC);
    effect eVisual = EffectVisualEffect(VFX_FNF_SMOKE_PUFF);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVisual, oPC, 1.0);
  }
}

スクリプトを保存して、テストしてみて下さい。(アミュレットをモジュール内に置くことを忘れないで下さい。)


このスクリプトには2点説明した方がいい箇所があります。最初は、次の行です。 int nHealing = FloatToInt ( IntToFloat( nDamageTaken ) / 2 );


基本的なアイディアは単純です。どれだけヒーリングすればいいのかを知るために、ダメージ量の半分の値を算出しています。それでは、IntToFloatFloatToInt はどういう意味でしょうか?int は整数であることを思い出して下さい。少数値は使用できません。2つの数字を割ったとき、必ず少数部分が出てくると思います。よって、整数を割ると少数部分が出てくる可能性が常にあります。


「float」は、少数部分を持った数字です。割り算をするので、まず整数nDamageTakenを少数値に変換する必要があります。よって、IntToFloat関数を使います。しかし、割り算をしたあとの最終的な結果は整数である必要があります。よって、逆にFloatToInt関数を使っています。この関数は、数字の小数部分を「切断」し、その結果を整数として返します。


実際の数字を例にして使ってみましょう。17ポイントのダメージを受けているPCがいるとします。17を小数に変換すると、17.0になります。それから、17.0を半分に割ります。すると、8.5になります。それを再び整数に戻し、小数部分をカットします。すると、8になります。つまり、8ポイントのダメージがヒーリングされることになります。


2点目は、スクリプトの下部にある「Effect」関数の部分です。オブジェクトに何らかの影響を直接与えたい場合には、エフェクトを使う必要があります。ヒーリング、視覚効果、特殊能力、ノックダウン、これらは全て1つかそれ以上のエフェクトで構成されています。このスクリプトでは、2つのエフェクトを使っています。1つはヒーリング、もう1つはプレイヤーの周りに表示される煙の視覚効果です。(アミュレットは完全な能力を持っていないと仮定しているので、煙がふさわしいと思いました。) それぞれのエフェクト処理は、2つの部分から構成されています。エフェクトの定義部分とPCに適用する部分です。


ヒーリングのエフェクトを使うときには、まず、どれくらいヒーリングするかを伝える必要があります。それが、「effect eHeal = EffectHeal(nHealing);'」です。そして、「ApplyEffectToObject ( DURATION_TYPE_INSTANT , eHeal, oPC);.」で、PCをヒーリングしています。エフェクトを適用する場合、DURATION_TYPE_INSTANT は、エフェクトが即座に適用され終了するということを意味しています。eHeal は、定義したエフェクトです。そして、oPC はエフェクトの対象です。


2番目のエフェクトも似ています。煙の視覚効果を定義して、それをPCに適用しています。このエフェクトは何秒間か持続します。よって、_TEMPORARY が設定されています。そして、エフェクトと対象を指定しています。最後の数字は、エフェクトの持続時間です。


数多くの使用可能なエフェクトがあるので、使用したいエフェクトを捜すのはとても苦労しますが、全てのエフェクトは、基本的には同じ方法で使用します。


例 2: アルフレッドのリング


スクリプト作成にだけ関心がある人は、この段落は飛ばして下さい。この段落は、私の古い友人の一人で、素晴らしいD&DそしてDMであった人を思い出しながら書きたいと思います。彼がユーモアのあるキャンペーンに参加した時の話です。不運にも、私はそのキャンペーンに参加していなかったのですが、数多くの話を聞きました。彼のキャラクターは「Alfred the were-chicken」でした。キャラクターのバックストーリーは覚えていませんが、全ての獣人的なパワーを当たり前のように持っていました。満月に変身し、銀の武器以外は効き目がなく、そしてもちろん、特定の動物をコントロールできました。AD&D1stエディッションのプレイヤーハンドブックを持っている人なら、1匹のニワトリを家畜にするためのコストを見つけることができます。それは銅のかけら1つです。200の銅のかけらで1ゴールドです。したがって、2ゴールドあれば、400匹のニワトリの大軍を持つことができました。確かに個々のニワトリは大したことありませんが、一度に400匹のニワトリに囲まれ、それら全てにツメで引っかかれ、くちばしで突かれるとしたらどうでしょう。身震いしますね。とにかく、このアイテムはその「Alfred the were-chicken」の思い出です。


このリングの能力はニワトリを召喚することです。地面をクリックすると、そこにニワトリを召喚します。クリーチャーをクリックすると、ニワトリはクリーチャーを攻撃します。(ちょっと待って下さい。ニワトリが勇敢に戦うかは分かりません。)


先に進んで、アイテムを作りましょう。基本的に、最初に作ったアイテムと作り方は同じですので、ステップ・バイ・ステップでは説明しません。アルフレッドのリングという名前のリングを作って、タグをCHCKRINGにして、1日1回使用の制限はかけません。(役に立つクリーチャーであれば、バランスを崩すでしょうが、ニワトリなら大丈夫ですよね?)


このアイテムを機能させるためには、同じスクリプトに以下のスクリプトを追加する必要があります。


// 以下のセクションは、アルフレッドのリングのためのスクリプトです。
// ニワトリを召喚します。クリーチャーに対して使うとニワトリはクリーチャーを攻撃します。
if (GetTag(oUsed) == "CHCKRING")
  {
    // リングが何処に使われたかを調べます。
    location lTarget = GetItemActivatedTargetLocation();

    // 出現エフェクトを設定します。
    effect eChickIn = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3);

    // ニワトリを召喚します。
    object oNewChicken = CreateObject(OBJECT_TYPE_CREATURE, "nw_chicken", lTarget, TRUE);

    // リングの使用対象がクリーチャーであれば、ニワトリは少し間隔を置いて召喚されます。
    // よって、ロケーションを更新して、エフェクトを適用します。
    lTarget = GetLocation(oNewChicken);
    ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eChickIn, lTarget, 1.5);
    
    // 最後に、対象となっているオブジェクトがあるかどうかを調べ、あれば攻撃します。
    object oEnemy = GetItemActivatedTarget();
    if (GetIsObjectValid(oEnemy))
      AssignCommand(oNewChicken, ActionAttack(oEnemy));
  }

スクリプトの頭部分のコメントも更新して下さい。(毎回更新するのが面倒なのは知っていますが、内容を頭の中に入れる良い練習になります。)


次に進んで、モジュールを保存し、テストしてみて下さい。(テストするときの注意: ニワトリは実際には、友好的な物に対しては攻撃しません。よって、上手く攻撃するようにファクションを少しいじる必要があります。一度試してみると面白いです。ニワトリは攻撃はしますが、その後怯えて逃げ出します。)


いくつかの注意事項


スクリプトで実現可能な色々なアイテムのアイディアが湧いてくると思いますが、それらのアイテムはモジュール内においては2、3個作成する位に、自分自身で制限すべきです。1つの理由は、バランスです。そのようなアイテムを多く作成すればするほど、キャラの個性が薄れていきます。別の理由は、作業能率です。全てのエフェクトが1つのスクリプトに書かれるので、多くのアイテムを作成するとそれだけスクリプトが巨大になってしまいます。


その他の注意事項は、アイテムに関するスクリプトは別のモジュールで動くとは限らないということです。もちろん、OnActivateItemスロットのスクリプトを他のモジュールにカット・アンド・ペーストすることはできますが、それだけでは上手く動作しないでしょう。


これらの理由で、特殊な機能をアイテムに与えるときは、プロット・アイテムとして使うのが一般的です。強制ではありませんが、考慮する必要はあるかもしれません。


演習


これらのアイテムをどのように利用するかは、自分自身のアイディアがあると思いますが、必要であれば以下の演習にトライしてみて下さい。

  1. 異なった場所に2つの祭壇を作ります。いずれか1つに祈ることで、そこがPCの召還地点として設定されます。そして、あるアイテムを使うとその召還地点にPCがテレポートするようにして下さい。(中くらいの難易度)
  2. PCがアルフレッドのリングを使うことに夢中になると、多くのニワトリが出現し、ゲームのパフォーマンスに影響を与えるに違いありません。一定時間経過後に、ニワトリの召喚が解除されるように修正してみて下さい。(正しい関数を見つけられれば簡単です。)
  3. 使うと対象をヒーリングしますが、使用者から経験値100を取り去るワンドを作って下さい。(中くらいの難易度。ワンドにビームのエフェクトを加えると難易度は高くなります。)

いずれにしろ、楽しみながらやって下さい。





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