Tuesday, June 6, 2017

ターゲットSpecificなコールバック関数 その3

街がターゲットの場合。EditorIDは基本的には、クエストユニークなインスタンス要素に付けるパラメータで、「街」のように他のScriptedクエストからも使う要素に付けるとよろしくない。

ではどうしよう、ということで、街がクエスト毎にユニークな名前を持てるようにしてみる。具体的には、街データそのものには「ユニークな名前」データは持たせずに、街のエイリアスを作って、そのエイリアスにユニークな名前を持たせることで、コールバック関数名に利用できるようにしてみた。:D

画像の例では、CreateAlias関数で、ターゲットの街のIndexを指定して、EventScriptで、どのスクリプトの管轄かを指定。AliasNameをその「ユニークな名前」という形でとりあえず。


AliasNameとしたけど、キャラ・アイテムはEditorIDというのを使っていて、混乱するので、「エイリアスの」ということでこれもEditorIDにしようかなあ?
この、コールバック関数名の命名以外でも、「エイリアスのユニークな名前」でターゲット指定できるようにできれば、その方が良さそう。(エイリアスそのものを各種関数にパラメータとして渡す、というのは、色々難しいのでナシ)

Monday, June 5, 2017

ターゲットSpecificなコールバック関数 その2


前の記事に書いたように、こんな感じの記述で、システムからコールバックを受けられるように出来た。:D まだ呼び出しテストしかしてないけど、呼び出せたのでok。

上の例は、
  • クエスト指定(EventScriptパラメータをセット)したキャラに、EditorIDをセット
  • クエスト指定をしたアイテムの、CallbackModuleパラメータに、同クエストスクリプトのサブモジュール名をセット
  • そのアイテムが、(EditorIDを持った)キャラのインベントリに入った時、クエストスクリプトのサブモジュールの中のOnAddToCharacter_EditorID()がシステムから呼ばれる
アイテムごとにサブモジュールを分けたり分けなかったり、必要に応じて。
OnAddToCharacter_PC() か OnAddToCharacter_player()で、PCのインベントリに入った時のコールバック関数を作れる。

Luaはフレキシブルだなあ。:)

Tuesday, May 23, 2017

ターゲットSpecificなコールバック関数 その1

TES4の、アイテムのスクリプトのひとつ。


OnAddというのは、誰かのインベントリに入った時に呼ばれる関数なんだろうけど、どうも見た感じ、playerのインベントリに入った時と、NivanDalviluREFのインベントリに入った時とで、呼ぶ関数を分けられるみたい。

こうすると、「誰かのインベントリ」の、「誰」の部分の判定をコードに書かなくて良いので、有用だと思うんだけど、、
Luaだとこういう記述はできないと思うので、さて、どうしようということで、
function ITEMSCRIPT:OnAdd__EDITORID()
という感じで関数名にEditorIDを書くと、そのIDのキャラがターゲットの時に呼ばれる、という形にならできるかなあ(ハイライターも効かなくなるから見やすくないし、なんか格好悪い気もするけど)。

続く

Tuesday, May 2, 2017

「エイリアス」によるデータ操作


赤丸の部分でキャラクターに、「TEST01」というEditorIDをセット。
青の部分で、TEST01というEditorIDを持ったキャラクターの「エイリアス」を作成。
すると、紫の下線部分のような形で、データにアクセス可能に。

CreateCharacterAlias関数は、character[ EditorID(この場合"TEST01") ]を作って、それを戻り値として返しますcharacter[~]はグローバルに作られるので、戻り値を無視して、character["TEST01"]を使うのもアリです。見やすい方で。
player(黄色の下線)は、プレイヤーキャラクターへのエイリアスとして、ゲーム開始時に自動的に作成されます。

なぜ「エイリアス」を使うのかというと

ld25では、ほとんどのゲームデータはシステム(delphi)側に置いているんですが、Lua側とシステム側のメモリは、それぞれ独立していて、直接代入などで読み書き出来ないためです。
上の例で言うと、Lua側には各エイリアスの「Money」の実際のデータは存在しておらず、エイリアスは自身のMoneyパラメータにI/Oがあった時に、「スタックを使ってシステムと値のやりとりをする」関数を走らせて、システム側のエイリアスのターゲットキャラのMoneyデータに対して操作します。

とりあえず、そのエイリアスの動作確認ができたので、キャラクター以外のデータもそう出来るようにしていきます(キャラクターエイリアスもまだパラメータ全部は書き終わってないですが)。:D

Saturday, April 29, 2017

"NPCとの対話ウィンドウ"ではない選択肢表示ウィンドウ

これがあるの忘れてた。

Pillars of Eternityにあった、テキストと絵と選択肢だけで進む、アレみたいなウィンドウ。
これはまた、questTopicとは別枠で作った方が良さそう。
こっちの機能は、NPCとの会話に限らず、スクリプトの任意のタイミングで出せるので、ちょっと勝手が違う。あと、上半分の黒地で白文字の部分のデータ定義もあるので。

これを表示する関数の引数に、シーンIDを指定すれば、白文字部分・選択肢が全部表示される、というのがベストだけど…

Wednesday, April 26, 2017

AnswerTextについて

Genericな会話テキストの定義コード。画像の例は挨拶。

発話者の性別その他でフィルタリングした上で、その中からランダムな1個を表示する、ということをシステムがやっています。気にしないパラメータ(AllやNone)は省略可(デフォルト値としてAllやNoneが入るので)。

これはDialogue型というデータ枠ですが、AnswerText型で別枠に入れて、その枠の中をシステムが走査。このSceneの代わりに、EditorIDを指定できるようにすれば良いかなと思います。(EditorIDじゃなくてシーンIDと言った方が適切か)

噂話についても、発話テキストをstring型で定義するよりは、こういう型のEditorID(シーンID)を指定する方が、発話者ごとに微妙にテキストを変えられるので良いかも。Genericな噂ばなし用のRumor型という、似た処理をするものがあるので、それをシーンID指定できるようにすればok。

フィルタリング項目にFaction指定がまだ無いけど、Factionの名前かEditorIDを指定できれば良さそう。

NPCとの対話

しばらく前に書いたスクリプトイベントの、NPCとの対話で、PCがする発言の選択肢を表示する部分。(選択の結果については別のコールバックで処理)

現状は上の画像のような力技で書いていて、さすがにこれはダメなので、
  • 条件付きの選択肢テキストを定義しておけば、対話ウィンドウの表示時に、システムが勝手に選んで表示
  • 選んだ選択肢ごとの結果の処理も、選択肢テキストとカップリングで定義
できるようにしたいという感じ。

それで、自分の能力では、下の画像のようになら出来るかなあというイメージ。
このコードを、少なくとも対話ウィンドウが表示される前の、どこかのタイミングで走らせる。(タイミングはスクリプト書く側の自由。=これを走らせるコードをスクリプトに書く必要アリ)
  • ID: TESで言うEditorID
  • AnswerTextID: 対話の相手が、選択肢への返答として発する、テキストのEditorID
  • Condition: booleanを返すLuaコード
  • Answer: 選択肢を選択したら走らせるLuaコード*1
  • Result: 選択肢を選択したら走らせるLuaコード*2
全部string型になっちゃうので、ちょっと見難いけど。。

クエストspecificな噂テキスト(TESではConversationと言ってるぽい)も、こんな感じで定義できそう。(データ的には、ConditionとAnswerTextIDだけで良い)

AnswerTextについては、別の記事として書きます。

*1 AnswerじゃなくてResultですね。*2が正解です。