拘束してみた

Modを作ろう

Requiemには敵が恐れをなして逃げる機能があります。それだけでつまらないので、拘束できるようにしてみました。

設計

対象を拘束する操作を何らかの形で実装する必要があります。

思いつく操作はいくつかあります。拘束するのに会話から行うのは少し違うような気がしますし、戦闘中に会話している暇はありません。ホットキーはコントローラーはおろか、キーボードにすら空きがないため、これ以上増やしたくないです。魔法(パワー)も切り替えが面倒です。

単純に、逃げ出したActorをアクティベートしたら拘束されるようにしました。

拘束のポーズはバニラに用意されているので、それをそのまま使います。暗殺者ギルドのクエストの最初の方で出てくるやつです。

アクティベートを捕捉

Perkを作ってプレイヤーに付与します。

Entry Pointは2つ用意します。

拘束用のEntry Point

こんな感じで作ります。

条件はしっかり付けないと、予期せぬ誤動作の原因となります。

IsFleeingが1なら怯えて逃げ出しているという条件です。

戦闘の対象がプレイヤーである、という条件も入れてありますが、NPC同士の戦闘に介入したいのなら取ってもいいでしょう。

拘束中のEntry Point

拘束したらルートしたいですし、解放する処理も必要です。

拘束はスペルを持たせることにしたので、それを条件に加えます。

Papyrus Fragment

Perkにスクリプトを付けます。それぞれのEntry Pointでスクリプトが実行されるようにします。

拘束用Perkのスクリプト (papyrus)

;BEGIN FRAGMENT CODE - Do not edit anything between this and the end comment
;NEXT FRAGMENT INDEX 7
Scriptname eqPerkActivationScript Extends Perk Hidden

;BEGIN FRAGMENT Fragment_5
Function Fragment_5(ObjectReference akTargetRef, Actor akActor)
;BEGIN CODE
; Activate Living Actor (Hostile, Fleeing)
Int result = eqQuestMain.ShowMessage(eqMsgDoYouWantToRestrain, akTargetRef, aiLevel = 0)

if result == 0
    (akTargetRef as Actor).AddSpell(eqAbilityRestrained)
endif
;END CODE
EndFunction
;END FRAGMENT

;BEGIN FRAGMENT Fragment_6
Function Fragment_6(ObjectReference akTargetRef, Actor akActor)
;BEGIN CODE
; Activate Living Actor (Restrained)
Int result = eqQuestMain.ShowMessage(eqMsgWhatDoYouWantToDo, akTargetRef, aiLevel = 0)

if result == 0
    Int h = ModEvent.Create("emOpenContainer")

    if h
        ModEvent.PushForm(h, akTargetRef)
        ModEvent.Send(h)
    endif

    Utility.Wait(0.5)

    String cmd = "\"" + PO3_SKSEFunctions.IntToString(akTargetRef.GetFormID(), true) + "\".openactorcontainer 1"
    ConsoleUtil.ExecuteCommand(cmd)
elseif result == 1
    (akTargetRef as Actor).RemoveSpell(eqAbilityRestrained)
endif
;END CODE
EndFunction
;END FRAGMENT

;END FRAGMENT CODE - Do not edit anything between this and the begin comment
Message Property eqMsgDoYouWantToRestrain Auto
Message Property eqMsgWhatDoYouWantToDo Auto

Spell Property eqAbilityRestrained Auto

自前のフォロワー拡張Modに作ったのでFragmentのインデックスが中途半端ですが、作るPerkのインデックスに合わせます。

メッセージですが、「拘束しますか?」と「何をしますか?」を作って紐づけます。

それから拘束を実現するアビリティも用意して紐づけます。

拘束中の対象のインベントリを開く方法がわからなかったので、コンソールコマンドのOpenActorContainerを実行しています。そのため、PowerOfThree Papyrus ExtenderとConsoleUtilが必要になります。

拘束するアビリティ

常時発動型のSpellとMagic Effectを用意します。

Magic Effectに付けるスクリプトは以下になります。

eqEffectRestrainedScript (papyrus)

Scriptname eqEffectRestrainedScript Extends ActiveMagicEffect


Event OnEffectStart(Actor akTarget, Actor akCaster)
    akTarget.SetRestrained(true)
    ;akTarget.SetActorValue("Aggression", 0)
    akTarget.StopCombat()
    akTarget.SheatheWeapon()

    Utility.Wait(1.0)

    Weapon kWeapon = akTarget.GetEquippedWeapon(abLeftHand = false)

    if kWeapon
        akTarget.UnequipItemEx(kWeapon, equipSlot = 1) ; Right Hand Slot
    endif

    kWeapon = akTarget.GetEquippedWeapon(abLeftHand = true)

    if kWeapon
        akTarget.UnequipItemEx(kWeapon, equipSlot = 2) ; Left Hand Slot
    endif

    Debug.SendAnimationEvent(akTarget, "IdleBoundKneesStart")
EndEvent


Event OnEffectFinish(Actor akTarget, Actor akCaster)
    if akTarget.Is3DLoaded()
        Debug.SendAnimationEvent(akTarget, "IdleChairExitStart")
    endif

    akTarget.SetRestrained(false)
EndEvent


Event OnCellAttach()
    GetTargetActor().SetRestrained(false)
EndEvent

Magic EffectはArchtypeをCalmに、Actor ValueをAggresionにします。これでこのアビリティを付与している最中はAggressionが低下するので戦闘から離脱する状態になってくれます。

拘束はSetRestrainedで移動を禁止したあとに拘束用アニメーションを再生させています。

アクティベート時のメッセージ

対象の名前をメッセージに含めるために、わざわざクエストを用意して対象をReference Aliasに入れるという面倒なことをしています。省いてメッセージも簡略化すれば楽になります。

拘束用

拘束中の操作用

こちらは選択肢がルート、解放、キャンセルの順です。Perkのスクリプトと関連しているので順番に注意します。

不具合について

拘束中にゲームをセーブしてロードすると、アニメーションが再現されないことがあるようです。これは面倒なので放置しています。

拘束中の対象がセルにAttachされたタイミングで拘束を解いています。これは、色々ある面倒な処理にたいする対策です。

拘束したままエリア移動すると、現在アクティブなセルが切り替わる都合上、対象はセルからDetachされます。そこで魔法が切れる場合と切れない場合があります。切れるのはセルがメモリにない場合、切れないのはセルがまだメモリに残っている場合です。プレイヤーが移動した直後は、さっきまでいたセルはメモリに残っているので、魔法は切れません。この状態でゲームをセーブしてSkyrimを再起動すると、OnEffectFinishは発火しないが魔法は切れているという状態になります。

かなりややこしいので、魔法は切れていないがセルを移動して付いてきた場合に、SetRestrainedをオフにして拘束を解いています。必ず付いてくるというわけでもないようなので、付いてこなかったときはそのままですが、アビリディは付与されたままなので、後日再会するようなことがあれば、その時はまたOnEffectStartが発火するので拘束された状態になります。

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