Top Downloads&ScreenShots 掲示板 Love Beer!! 家具MODを修正 日時を取得する練習 四季の変化 木のカタログ
家具MOD(barter of furniture.esp)の不具合報告をいただいたので、私に直せるものかどうか、がんばってみます。
不具合の内容は、「コンテナ系のアイテムを使っていると、 PCの荷物の重量が 0 になり、一旦セーブすると、0 のままで何をしても元に戻らない」という深刻なもの。
実は、MODの動作確認をするとき、PCの荷物の重量には全く注意を払っていませんでした。すいません。

不具合を再現する

ゲームを起動して、不具合が再現するかどうかコンテナの Crate (容量200)をいじって試してみたところ、 「落として、拾って、また落とす」と 100%の確率で荷物重量が 0 になった。
さらに調べたところ、武器屋などで総重量 200 以上の買い物をすると PC の荷物の重量に 33 とか表示された。 要するに、アイテムを落とすときにコンテナの容量を重さと見なして、荷物重量から引いてしまっていたらしい。
家具 MOD は、家具が Inventory にある時は MiscItem で、地面に落とした時に Activator やコンテナと入れ替える ( The Portable Bedroll という MOD のスクリプトを参考にしました。)ということをしているので、ここのスクリプトに間違いがあるみたいだ。
begin _Inventory_Crate_01	;スクリプト開始
	short OnPCDrop
	if ( OnPCDrop == 1 )	;プレイヤーがこのオブジェクトを落とした時
		Disable	;このオブジェクト(MiscItem)を削除
		Player->Drop, "Barter_Crate_01", 1	;代わりにオブジェクト「Barter_Crate_01」(コンテナ)を落とす。
		Set OnPCDrop to 0	;初期化
	endif
end _Inventory_Crate_01	;スクリプト終了
どうも関数 Drop は、Inventory からアイテムを取り出して地面に落とすという機能みたいで、コンテナはもともと Inventory に無いのに、Drop させてしまったのが悪かったらしい。そしてこの不具合が椅子やテーブルに起こらなかったのは、 重量も容量も無いオブジェクトだったからみたいだ。

不具合を修正する

不具合の原因がわかった( と思った )ので修正する。
旧 Player->Drop, "Barter_Crate_01", 1	;プレイヤーがオブジェクトを落とす
新 PlaceAtPC, "Barter_Crate_01", 1, 64, 0	;プレイヤーの所にオブジェクトを置く
実は、参考にさせてもらった MOD、The Portable Bedroll は、関数 PlaceAtPC を使っていた。それを Drop に変更したのは、Bedroll と違って 家具のオブジェクトをこの関数で置くと、地面に埋まってしまうからだった。
動作確認すると、荷物重量が 0 になる不具合は起こらないが、Crate が地面に半分埋まっている。

もう1つの不具合

荷物重量が 0 になる不具合は、2回目に落としたときに起こり、1回目にはない。そして1回目に落とした時は MiscItem のままで、 コンテナに換わってはいなかった。どうも1回目にはスクリプトが動いていないみたいだけど、原因がわからない。
どこが悪いのかわからないので修正できないけど、同じ操作をしてるのに結果がちがうのは良くないので、 常に MiscItem のままで地面に置かれるようにしちゃうことに決めた。(つまり、アイテムを地面に置くときにはスクリプトを使用しないようにした。)
これは、地面に置かれた MiscItem の Crate を使用したときに、拾うか、コンテナに変換するか、を選択させるスクリプト。
(お店で買った家具は梱包されていて包みを解いて組み立てないと、家具として使えないという設定。 梱包状態のオブジェクトは後で作ることにする。)
begin _Inventory_Crate_01
	short messageOn
	short button
if ( OnActivate == 1 )	;使用すると
	MessageBox, "Crate", "Pick Up", "Unpack", "Cancel"	 ;拾う、梱包を解く、キャンセル
	set messageOn to 1
endif
if ( messageOn == 1)
	set button to GetButtonPressed
	if ( button >= 0 )
		set messageOn to 0
	endif
	if ( button == 0 )
		Disable	;Activateにしても拾えないので、削除してから、
		player -> AddItem, "Inventory_Crate_01", 1	;アイテム追加
	elseif ( button == 1 )
		Disable	;削除して
		PlaceAtPC, "Barter_Crate_01", 1, 64, 0	;アイテムを置く
	elseif ( button == 2 )
		return
	endif
endif
end _Inventory_Crate_01
このスクリプトの問題点は、MiscItem の Crate を落とした場所とそれをコンテナに変更したときに 置かれる場所が一致しないということ。 例えばテーブルの上に Crate を置いても、コンテナに変換したときに足元に移動してしまう。

グローバル変数で座標の受け渡しをする

global_furn
いい方法が浮かばなかった時に、アブソルジャーさんの「グローバル変数に記憶させておく」という書き込みがあり、 グローバル変数で、MiscItem の座標を渡せるかもしれないと思い試すことにした。
begin _Inventory_Crate_01
	short messageOn
	short button
if ( OnActivate == 1 )
	MessageBox, "Crate", "Pick Up", "Unpack", "Cancel"
	set messageOn to 1
endif
if ( messageOn == 1)
	set button to GetButtonPressed
	if ( button >= 0 )
		set messageOn to 0
	endif
	if ( button == 0 )
		Disable
		player -> AddItem, "Inventory_Crate_01", 1
	elseif ( button == 1 )
		set furnPX to ( GetPos, x )	;グローバル変数 furnPX にオブジェクトのX軸座標を代入
		set furnPY to ( GetPos, y )
		set furnPZ to ( GetPos, z )
		set furnAX to ( GetAngle, x )	;グローバル変数 furnAX にオブジェクトのX軸角度を代入
		set furnAY to ( GetAngle, y )
		set furnAZ to ( GetAngle, z )
		set furnPAset to 1	;オブジェクトの座標・角度が記録されたというフラグ
		Disable
		PlaceAtPC, "Barter_Crate_01", 1, 64, 0
	elseif ( button == 2 )
		return
	endif
endif
end _Inventory_Crate_01
下はコンテナ Crate のスクリプト
これで MiscItem とコンテナの位置が一致して(一瞬表示されるけど)、コンテナが地面に埋まることも無くなった。
begin _Barter_Crate_01
	short messageOn
	short button
	short openOn
	short setOn
	float localfurnPX
	float localfurnPY
	float localfurnPZ
	float localfurnAX
	float localfurnAY
	float localfurnAZ

if ( OnActivate == 1 )	;ここからコンテナを使用したときの動作
	MessageBox, "Crate", "Pick Up", "Open", "Move Right", "Move Left", "Move Forward", "Move Back", "Move Up", "Move Down", "Cancel"
	set messageOn to 1
endif
if ( messageOn == 1)
	set button to GetButtonPressed
	if ( button >= 0 )
		set messageOn to 0
	endif
	if ( button == 0 )
		set openOn to 2
		MessageBox, "Take All !!"
	elseif ( button == 1 )
		set openOn to 1
	elseif ( button == 2 )
		Move, x, 640
	elseif ( button == 3 )
		Move, x, -640
	elseif ( button == 4 )
		Move, y, 640
	elseif ( button == 5 )
		Move, y, -640
	elseif ( button == 6 )
		Move, z, 640
	elseif ( button == 7 )
		Move, z, -640
	elseif ( button == 8 )
	endif
endif

if ( openOn == 1 )
	if ( menumode == 0 )
		activate
		set openOn to 0
	endif
endif

if ( openOn == 2 )
	if ( menumode == 0 )
		activate
		Disable
		player->addItem, "Inventory_Crate_01", 1
		playSound "Door Latched Two Open"
		set openOn to 0
	endif
endif

if ( furnPAset == 1 )	ここからは MiscItem からコンテナに変換されたときのスクリプト
	if ( setOn == 0)
		set localfurnPX to furnPX	;グローバル変数は座標や角度に直接代入できないようなのでローカル変数に代入する
		set localfurnPY to furnPY
		set localfurnPZ to furnPZ
		set localfurnAX to furnAX
		set localfurnAY to furnAY
		set localfurnAZ to furnAZ
		setPos,x,localfurnPX	;ローカル変数の値をオブジェクトの座標・角度に指定
		setPos,y,localfurnPY
		setPos,z,localfurnPZ
		setAngle,x,localfurnAX
		setAngle,y,localfurnAY
		setAngle,z,localfurnAZ
		set setOn to 1	 ;MiscItem からコンテナへの変換が完了したというフラグ
		set furnPAset to 0	;ここからローカル変数・グローバル変数の初期化
		set localfurnPX to 0
		set localfurnPY to 0
		set localfurnPZ to 0
		set localfurnAX to 0
		set localfurnAY to 0
		set localfurnAZ to 0
		set furnPX to 0
		set furnPY to 0
		set furnPZ to 0
		set furnAX to 0
		set furnAY to 0
		set furnAZ to 0
	endif
endif

end _Barter_Crate_01
スクリプトが長くて、自分でもわけがわからない状態ですが、軽く動作確認してみたところ特に不具合はありません。
もう少し調べて、問題無さそうなら、サウンドを設定して、梱包時のオブジェクトを作ってUPしようと思います。
Top Downloads&ScreenShots 掲示板 Love Beer!! 家具MODを修正 日時を取得する練習 四季の変化 木のカタログ