チェスト、死体などへアクセスした時、アイテムが複数個ある場合はデフォルトが全て取る

試行錯誤した結果、以下の処理で落ち着きました。

1個数入力メニューが表示された瞬間「OK」ボタンで閉じる。
2左Shiftが押されている場合は個数を1に変更して強制「OK」。
3左Ctrlを押している間は個数入力メニューを閉じない。

このため、3つ以上のアイテムをクリックすると一瞬だけ個数入力メニューが表示されます。
スクリプトの呼び出し間隔をどんなに短く設定しても、一瞬だけ表示されてしまうので諦めました。
個数入力の煩わしさを低減することが目的なので。


ScriptName UI_Behavior

float fQuestDelayTime

begin MenuMode 1016  ;quantity_menu
  let fQuestDelayTime := 0.1  ;もっと長くてもいいかも
  if IsKeyPressed2 42  ;左Shift押してる?
    If GetMenuHasTrait "quantity_background\quantity_scroll\user7" 1016
      SetMenuFloatValue "quantity_background\quantity_scroll\user7" 1016 1
    endif
  endif
  if IsKeyPressed2 29 == 0  ;左Ctrl押してないなら勝手にOK
    if GetMenuHasTrait "quantity_background\quantity_button_okay\id" 1016
      ClickMenuButton "quantity_background\quantity_button_okay" 1016
    endif
  endif
end

今後の改善点。
左Shift、左Ctrlを任意のキーに変更可能にする。

GetMenuHasTraitやClickMenuButtonに指定しているパスは、quantity_menu.xmlのXMLファイルを見ないと分かりません。
メニューの背景画像やボタンなんかの配置情報はxmlファイルに定義されてます。
これらのxmlファイルは、Oblivion - Misc.bsaに入ってます。
OBMMに付属してるBSAブラウザでファイルを抽出できます。

個数入力メニューのOKボタンは、quantity_button_okayという名前が付けられていて、quantity_backgroundの子要素として配置されてます。
子要素を参照するには親要素から子要素という順番にアクセスする必要があるため、quantity_background\quantity_button_okayというアクセスが必要になります。

個数入力メニューかどうかは、1016という値で判断しているようです。
全てのメニューには番号が割り当てられていて、1016が個数入力メニューに相当します。

Menu Code一覧
http://obse.silverlock.org/obse_command_doc.html#Menu_Code

とりあえず、作成中のMODの名前は 0ssan_auriga UI Behavior Mod とします。

コンテナ、取引メニューでカーソル位置のアイテムの個数を取得する

何の役に立つかは分かりませんが。

begin MenuMode 1008
  ref active
  ;アイテムにマウスカーソルが触ってるか
  let active := GetActiveMenuSelection
  if active == 0
    ;ひとつも触ってないから終了
    return
  endif
  ref owner
  ;コンテナを表示してるのかインベントリを表示してるのか
  short view
  let view := GetContainerMenuView
  if view
    ;インベントリを表示してる
    set owner to player
  else
    ;コンテナを表示してる
    set owner to GetActiveMenuRef
  endif
  if owner == 0  
    ;何故か取得失敗
    return
  endif
  ;コンテナかインベントリにある全ての項目を取得
  ;この参照はリストに表示されてる項目(list item)を指している
  ;道具としてのアイテムへの参照じゃないので注意
  ;アイテム名は取得できるが個数が取得できない

  array_var items
  let items := owner.GetItems
  ;取得した項目の中でカーソルが触れている項目が何番目にあるか調べる
  short active_index
  let active_index := ar_find active items
  if active_index < 0 || active_index >= ar_size items
    ;何故か返って来た値が範囲外
    return
  endif
  ;カーソルが触れている項目の道具としてのアイテムへの参照を取得
  ref object
  let object := owner.GetInventoryObject active_index
  if object
    ;アイテムの個数を取得
    short count
    let count := owner.GetItemCount object
    ;コンソールにカーソルが触れているアイテム名と取得したその個数を表示
    print "ItemName:" + (tostring active) + " Quantity:" + (tostring count)
  endif
end

カーソルが触れているアイテムの個数を取得したいだけなのに、このめんどくささ。
もっと簡単な方法があるかも知れません。
GetBarterItemQuantityを使ってみたら1しか返って来ませんでした。
使い方が悪かったようです。

コンテナは取引相手の所持品表示と、プレイヤーの所持品表示を切り替えられるので、どっちを表示してるか?を調べて、表示している方の所持品にアクセスしなきゃいけません。

気になったところは、参照型(ref)の変数に値をセットするとき、OBSEタイプのletを使うと怒られる場合があります。
letでセットできる場合もあり、どういう使い分けが必要なのかが分かりません。
現状はCSに怒られたら直してます…。

いちいち変数を宣言、解体するのが気になるという場合は、begin MenuMode 1008より前でまとめて宣言すれば良いかも知れません。
と言っても、スクリプト解析処理の詳しい挙動を知りませんので、スクリプトの書き方における好みの問題でしかないかも知れません。
例えば、スクリプト解析時に全ての変数の領域を確保してしまうなら、先に宣言しようが必要になった都度宣言しようが変わりはありません。
変数の宣言があった時に領域を確保して、ブロックが終わった時に領域が解放されるなら、意味はあると思います。
どっちなんでしょうね…。

このままだと、ただのサンプルコードですが、選択箇所のアイテムの個数を返す関数にすれば、何かの役には立ちそうです。

調べるにあたり、こちらのフォーラムを参考にしました。
ES Forum Archive > General TES Construction Set -- Oblivion > Want to Create SpellEffect to Drop All Items

Esc、Tabで閉じられないメニューを極力無くす 1

何でもかんでも閉じてしまえ!という場合は簡単なのですが、メニュー毎に微妙に対応を変えたい。
そうなると、全てのメニューに対して処理しなきゃいけません。

例えば、オプションメニューの場合は呼び出し元のポーズメニューに戻る。
会話ダイアログなら、きちんと会話終了ボタンを押した状態で終了する。

Escはスクリプト側の処理よりもポーズメニュー呼び出しの処理が優先されてしまうので、例えば、ロックピック操作中にEscを押すと、ポーズメニューが表示され、そこで更にEscを押すと、ポーズメニューとロックピックメニューが両方閉じるという処理になってしまいます。
Escはあくまでポーズメニュー呼び出し優先として割り切るしかなさそうです。

沢山あるので、一部を例として上げます。

・ロックピック
・オプション
・会話
・修理
・レベルアップ
・交換(チェスト、死体、商人など)


ロックピック
begin MenuMode 1014
  if IsKeyPressed2 1 || IsKeyPressed2 15  ;EscかTabキー
    CloseAllMenus
  endif
end
ロックピックメニューは、何故かClickMenuButtonだと閉じません。
ロックピックメニュー中、ポーズメニュー以外は表示しないので、CloseAllMenusで全てのメニューを閉じるようにしました。
でも、ほとんどのメニューはCloseAllMenusで閉じて問題ないと思います。

ロックピックメニューでの不具合を確認したので未対応にしました。

オプション
begin MenuMode 1015
  if IsKeyPressed2 1 || IsKeyPressed2 15
    if GetMenuHasTrait "options_background\options_return_button\id" 1015
      ClickMenuButton "options_background\options_return_button" 1015
    endif
  endif
end
オプションメニューの場合は、EscかTabを押した時、呼び出し元のポーズメニューに戻ります。
オプションメニューの一番上の戻るを選択したのと同じ動作です。

会話
begin MenuMode 1009
  if IsKeyPressed2 1 || IsKeyPressed2 15
    if GetMenuHasTrait "dialog_topics\dialog_button_layout\dialog_goodbye\id" 1009
      ClickMenuButton "dialog_topics\dialog_button_layout\dialog_goodbye" 1009
    endif
  endif
end
CloseAllMenusで問題ないなら、それで良いのですが、会話終了ボタンを押したときに何らかの処理が走るなら、会話終了ボタンを押した状態で終了させる方が良さそうです。
その辺の事情が分からないので、CloseAllMenusで強制的に閉じず、会話終了ボタンを押したのと同じ動作をさせます。

修理
begin MenuMode 1035
  if IsKeyPressed2 1 || IsKeyPressed2 15
    if GetMenuHasTrait "rep_button_exit\id" 1035
      ClickMenuButton "rep_button_exit" 1035
    endif
  endif
end
修理メニューはインベントリから呼び出される場合があるため、CloseAllMenusでインベントリごと閉じてしまうのは避け、修理メニューだけ閉じるようにします。
修理メニューの「閉じる」ボタンを押すのと同じ動作です。

レベルアップ
begin MenuMode 1027
  if GetMenuHasTrait "levelup_background\levelup_exit_button\id" 1027
    ClickMenuButton "levelup_background\levelup_exit_button" 1027
  endif
end
AF Level Modを導入している場合、いつでもどこでもレベルが上がるようになるため、レベルアップメニューがいちいちゲームを中断してくれます。
レベルアップメニューが出たら即座にCloseAllMenusで閉じてしまいたいのですが、どういうわけか、それをやるとレベルが上がらなくなります。
なので、レベルアップメニューが表示されたら勝手に「閉じる」ボタンを押してくれるという処理にしました。
「閉じる」ボタンを押しても、すぐにメニューは閉じませんが、ボタンをクリックする手間は省けます。

交換
begin MenuMode 1008
  if IsKeyPressed2 28 || IsKeyPressed2 156 ;Enter or Num Enter
    If GetMenuHasTrait "cont_background\page_layout\cont_contents\cont_button_take_all\id" 1008
      ClickMenuButton "cont_background\page_layout\cont_contents\cont_button_take_all" 1008
    endif
  endif
  if IsKeyPressed2 1 ; Esc
    If GetMenuHasTrait "cont_background\page_layout\cont_contents\cont_button_exit\id" 1008
      ClickMenuButton "cont_background\page_layout\cont_contents\cont_button_exit" 1008
    endif
  endif
end
交換メニューはTabには対応しているのですが、Escには対応していません。
商人との会話中に呼び出されることもあるため、CloseAllMenusは使いません。
もうひとつ追加した機能は、EnterかテンキーのEnterで「全て取る」を押したのと同じ動作をします。
全て取るボタンをクリックするのが面倒な時は、マウスを持ちつつテンキーのEnterを親指で押すなんて事ができるようになります。


今後の改善点

・閉じるキー、全て取るキーを設定可能にする。
閉じるキー(Esc,Tab)は自作関数に飛ばしてまとめて判定させた方が、今後のために良い。呼び出しが遅いので別の方法で。
・ロックピックメニューの自動解除キーを設定する(キーは設定変更可能に)。OBSEではムリっぽい。
・全てのメニューに閉じるキーを対応させる。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。