スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

OBSEのイベントハンドラに関して(その1)

拙作MOD「IgnoreFriendlyFireDamage」の公開を中止しましたが、その際「OBSEの動作仕様」を理由とさせて頂きました。
作者様のご厚意で使わせて頂いているOBSEという素晴らしいツールに対して、決してイチャモンをつけているわけではありません(´Д`;
「イベントハンドラを用いてMOD作成を行っている人が知っておかないと致命的なバグを引き起こす原因となり得る動作仕様」に関して詳しく説明させて頂きます。
 
個人的に思う「絶対に知っておくべき注意点」は2つあるのですが、まず「その1」として…
登録したイベントハンドラは他のセーブデータをロードしてもそのまま残って動作し続けてしまう。

サンプルMODをアップロードさせて頂きました。
http://www.4shared.com/file/4UR3RlFS/EventHandlerTest_1.html

MODのスクリプト部分を以下にコピペします。



scn aaaOnActivateEventHandler

ref activatedRef
ref activatingRef

Begin Function { activatedRef activatingRef }

 if activatedRef && activatingRef
  MessageBoxEx "%n が %n をアクティベートしました。" activatingRef activatedRef
 endif

End



scn aaaOnActivateQuestScript

float fQuestDelayTime

Begin GameMode

 set fQuestDelayTime to 0.0001

 ;Enterキーを押している?
 if IsKeyPressed2 28 ;Enter
  if 0 == SetEventHandler "OnActivate" aaaOnActivateEventHandler
   MessageBox "OnActivateイベントハンドラの登録に失敗しました。恐らく、すでにイベントハンドラは登録済みです。"
  else
   MessageBox "OnActivateイベントハンドラの登録に成功しました。"
  endif
 endif

End



まず実験を行うには「特定のひとつのセーブデータ」を扱いますので、それを決めて下さい。
以後そのセーブデータを「セーブデータA」を呼びます。

EventHandlerTest_1.espをアクティベートした状態でオブリを起動し、「セーブデータA」をロードしてください。
ロードしたらその辺の人をアクティベートして話しかけてみてください。
いつも通りにアクティベートできて何の変わりもないはずです。
EventHandlerTest_1.espは「キーボードのEnterキーが押された時に初めてイベントハンドラを登録するMOD」なので、現時点で何も起きないのは正常です。
では「キーボードのEnterキー」を押してみて下さい。
イベントハンドラが登録された旨のメッセージボックスが表示されるはずです。
その辺の人をアクティベートして話しかけてみてください。
「誰が何をアクティベートしたか」がメッセージボックスに表示されるはずです。
これはプレイヤー以外のアクターがアクティベートした情報も表示するので、しばらくボ~っとしているだけでも多数のアクティベート情報が出てきます。

ここまで実験したらセーブをしないで最初にロードした「セーブデータA」をロードし直してみてください。
「セーブデータA」は「まだイベントハンドラを登録していない状態」だったので「Enterを押すまでアクティベート情報のメッセージボックスは出てこない」はずですね?
ではその辺の人をアクティベートして話しかけてみてください。

これが私が問題点として考えている「登録したイベントハンドラが別のセーブデータをロードしてもそのまま残って動作し続けてしまう」現象です(´・ω・`)

この仕様により「任意のトリガを判定して動的にイベントハンドラを登録/解除する作りのMOD」は作ることができません。
セーブデータをセーブした時点とロードした時点とで、登録されているイベントハンドラの状態が一致するとは限らないからです。
(登録してあったイベントハンドラが解除されていたり、登録していないイベントハンドラが登録されていたり、不定な状態になっています)

従ってこのサンプルMOD「EventHandlerTest_1.esp」は「OBSEのイベントハンドラを扱うMODとしては不適切な作りになっている」と言えると思います。

実はこの動作仕様はMODの作り方次第で不具合を回避することができます。
「イベントハンドラの登録は初回起動時orロード直後に必ず登録する」ことで「イベントハンドラは常に登録されている状態であると想定する」のが解決策です(多分

しかし!この仕様を起因として別の問題が起きてしまうのです(´・ω・`)

(その2へ続く)
スポンサーサイト

コメント

非公開コメント

No title

うーん?OBSEがoblivionのセーブとは別枠のセーブデータを残す弊害って感じですかね。
別枠にしておかないと本気でセーブファイルの肥大化が心配だけど、
一つしか作らないから今回のような「動作終了したmodの情報を持ち続けてしまう」が発生してしまうのかな。

例えばmod側でリフレッシュタイミングを作るとかで回避可能になるんだろうか・・・?

コメントありがとうございます

ゆうひいろさん、コメントありがとうございます。

イベントハンドラの登録/稼働状態は現状どこにも(.obseにも)保存されていないようで復元されることがないようです。

・オブリを起動した時にはイベントハンドラは何も登録されていない状態
・その後ゲーム中に登録されたイベントハンドラは明示的に解除しないと別のセーブデータをロードしても残って動き続けている

こういう状態のようです。

ゆうひいろさんの仰るようにMOD側での対処をいろいろと模索しており、現状では
・毎フレーム常時監視を行い、タイトル画面に戻ったりロードを行う可能性がある状態を検知したら即座にイベントハンドラを解放する
・もしもキャンセルしてゲームに戻ってきたら再びイベントハンドラを登録し直す
という方法で回避できないかと思って現在は手元の「IgnoreFriendlyFireDamage」に組み込み済みで実験続行中です。

しかしMOD側からの監視はどうやっても完全なものではないと思うので、何らかのタイミングですり抜けてロードが出来てしまう可能性が高いと思うんですよね…

この辺は(その3)で記事としてまとめようと思っています。
プロフィール

r_basilico

バジリコ風味 (r_basilico)
Twitter: r_basilico
Steam: r_basilico
艦これ: 嫁艦は祥鳳

リンク
最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。