装備を身体に食い込ませる・その4

体型・装備

装備を組み合わせたときに食い込むようにしてみました。

今回の装備

Fox Collection 58を使います。

色々と改造をしました。

元は体型がUNPBOのようですが、CBBE 3BA v2にしました。

上下一体型ですが、分離しました。装備スロットのルールはTAWOBA準拠で上が32番、下が52番です。これで他の装備と組み合わせることができます。

紐はHDT-SMPで揺れるようにしました。

ブラの食い込み

Outfit Studioでスライダーを1つ用意して食い込ませます。

名前は何でもいいのですが、Pressed Braとしました。

BodySlideではこのスライダーを100%にしてメッシュを生成し、常に食い込むようにします。

リファレンス(裸体)込みなので、このブラを装備すると自動的に食い込んだ状態になります。

パンツの食い込み

Outfit Studioでスライダーを1つ用意して食い込ませます。

名前はPressedFox58としました。

ブラと違うのは、リファレンス(裸体)を含んでいないため、パンツだけを食い込ませるとリファレンス(裸体)にめり込んでしまいます。そこで、ブラにも同じ名前でスライダーを用意して、パンツに合わせてリファレンスをへこませます。

これで、ブラとパンツをセットで装備したときに食い込んだ状態にできます。

BodySlideではブラとパンツの両方とも、PressedFox58スライダーを0%にしてメッシュを生成します。デフォルトでは食い込んでいない状態になります。

キーワードを用意して装備につけておく

PressedFox58という名前のキーワードを用意して装備につけておきます。

espファイルの中でKeywordを定義してArmorに紐付けるという正攻法でもいいですし、KIDを使って用意してもいいです。

ゲーム内でスライダーを動的に切り替える

RaceMenuのNiOverrideを使います。

スライダーを100%にする場合は以下になります。

NiOverride.SetMorphValue(PlayerRef, "PressedFox58", 1.0)

スライダーを0%にする場合は以下になります。Morph自体を削除しています。

NiOverride.ClearMorphValue(PlayerRef, "PressedFox58")

スライダーを適用中かどうかをプロパティに保存しておき、必要なときのみMorphを操作すると負荷を軽減できます。

スライダーをActorに反映する

反映しないと見た目が更新されません。

SEですと以下でいいようです。

NiOverride.UpdateModelWeight(PlayerRef)

AEではRaceMenuの不具合なのか、これだと見た目が更新されません。ActorのWeightを変更すると更新されるようです。

Function RefreshWeight(Actor akTarget)
	Float fOldWeight = akTarget.GetActorBase().GetWeight()
	Float fNewWeight = fOldWeight - 1.0
	Float fNeckDelta = 0.0

	if fNewWeight < 0.0
		fNewWeight = fOldWeight + 1.0
	endif

	akTarget.GetActorBase().SetWeight(fNewWeight)
	akTarget.UpdateWeight(fNeckDelta)

	Float tmp = fNewWeight
	fNewWeight = fOldWeight
	fOldWeight = tmp

	akTarget.GetActorBase().SetWeight(fNewWeight)
	akTarget.UpdateWeight(fNeckDelta)
EndFunction

ここで問題になってくるのがNeckDeltaです。現在の値を取得する方法がないので、どこかに保存しておく必要があります。

簡単にはいかないため、Actor Weight ManagerにAPIを用意して呼ぶことにしました。

Int h = ModEvent.Create("awmRefreshPlayerWeight")

if h
	ModEvent.Send(h)
endif

ブラとパンツを同時に装備しているか調べる

プレイヤーの装備を調べて、キーワードで判定します。

Form kTop = PlayerRef.GetWornForm(0x4)	; 32 BODY
Form kBottom = PlayerRef.GetWornForm(0x400000)	; 52 Unnamed

Int iKeys = 0
String sMorphName = "PressedFox58"

if kTop && kTop.HasKeywordString(sMorphName)
	iKeys += 1
endif

if kBottom && kBottom.HasKeywordString(sMorphName)
	iKeys += 1
endif

if iKeys == 2
	; 上下セットで着用中
else
	; 片方もしくは両方着けていない
endif

検査するタイミング

厳密には装備を変更したときになりますので、OnObjectEquipped/OnObjectUnequippedイベントを見るということになりますが、これですと関係のないイベント発火が多すぎるので負荷が高くなってしまいます。

そこで、インベントリメニューを閉じた時に検査するようにします。

; あらかじめ予約しておく
RegisterForMenu("InventoryMenu")

; するとイベントを受け取れるようになる
Event OnMenuClose(String asMenuName)
	if asMenuName == "InventoryMenu"
		; 検査する
	endif
EndEvent

WornHasKeywordをうまく使うことで検査を簡略化できます。Morph適用前であればWornHasKeywordがfalseを返している間は装備を詳しく見るまでもないということです。

装備数を取得するWornApparelHasKeywordCountがPapyrusにあればもっと簡略化できそうなのですが、Condition Function限定のようです。

タイトルとURLをコピーしました