構成要素の説明
ホワイトランの前にいる馬車で、御者はBjorlamになります。
フォロワーはダークライトタワーのIlliaですが、誰でもいいです。
馬車で移動するプロセス
プレイヤーが御者をアクティベートして話しかけます。御者は普通のActorです。
目的地を聞かれるので答えます。ここで目的地が決定しますが、支払いはまだです。もう一度話しかけることで目的地を変更可能です。
プレイヤーが馬車をアクティベートして座ります。馬車は家具であり、椅子やベッドと同じです。
座ったことをトリガーに支払いが行われ、目的地にテレポートします。内部的にファストトラベル扱いなので時間が経過します。
フォロワーは近くにいるだけで乗ることはありません。
馬車システム
DialogueCarriageSystemというQuestが根幹になっています。さきほどのプロセスはすべてこのQuestに処理が実装されています。
御者はこのQuestのReferenseAliasに入っており、Skyrim各地にいる全員分が用意されています。
話しかけて目的地を選ぶことで、その御者に紐づいている座席の監視が始まります。また、御者のセリフが解禁されて「早く乗れ」などのセリフを言うようになります。
座席はQuestのCartRiderPlayerというReferenseAliasに入っており、プレイヤーが座ったことを検知するとプレイヤーを目的に移動させます。
Quest自体にもCarriageSystemScriptというScripitが設定されています。これがシステムの根幹部分です。
目的地を選んだときにTravel関数が呼ばれます。プレイヤーが座るとPlayerIsSitting関数が呼ばれます。
このScriptにはフォロワーを乗せる処理も書かれているのですが、どうやら使われていないようです。今回は独自の実装を追加するので使いません。
フォロワーが乗る処理を追加する
ポイントはどのタイミングでフォロワーを乗せるのか、そしてタイミングをどのように検知するのかです。
CarriageSystemScriptに手を加える方法
まずはCarriageSystemScriptに手を加える方法ですが、同じようにScriptを改変するModとの互換性がありません。その辺りを割り切って作る必要があります。
目的地を選んだときにTravel関数が呼ばれるので、そこに処理を追加すれば、プレイヤーが目的地を選んだ直後にフォロワーが乗ります。
プレイヤーが座るとPlayerIsSitting関数が呼ばれ、そこからSkipToDestinationSimple関数が呼ばれて目的地にテレポートするので、ここでフォロワーも目的地に移動させれば良さそうです。
あるいはOnPlayerFastTravelEndイベントを監視すれば、プレイヤーの移動のタイミングを検知できます。
間接的に監視する方法
御者は対象が決まっているため、御者をアクティベートしたことを検知するPerkを用意してプレイヤーに持たせておけば、御者との会話の始まりを検知できます。
馬車はDialogueCarriageSystemというQuestだと決まっているので、会話の始まりをきっかけにCartRiderPlayerというReferenseAliasを独自に監視して座席が埋まるのかどうか、埋まったのならプレイヤーが座ったのかを独自に監視をするようにすれば、CarriageSystemScriptには一切手を入れずに実装できそうです。
監視を省くと楽になるので、とにかく御者をアクティベートしたらフォロワーを馬車に乗せ、OnPlayerFastTravelEndイベントを持って移動の完了とみなしてフォロワーをプレイヤーの場所にテレポートさせれば、処理を少なくできます。
フォロワーが乗る動作
プレイヤーはアクティベートするため乗る動作がありますが、フォロワーが乗るためのアクティベートポイントがどうやらないようなので、動作がありません。
CarriageSystemScriptには3人まで乗せる処理が書かれているのですが、乗る場所を示すCartなるものが必要らしく、このホワイトランの馬車にはないみたいでした。
そこで、乗り込みはEVG Animated TraversalのVaultingを使い、座るのは透明の椅子を用意することにしました。
椅子はWoodenChair01をコピーして、メッシュのAlphaを0にしたものを用意します。名前をなくすことでクロスヘアを当てても表示されなくできます。
スペース的にはプレイヤーを入れて6人分ありそうです。
EVG Animated TraversalのVaultingをフォロワーに適用する方法はEVG Animated Traversalをフォロワーに対応させるにて解説しています。
アニメーションマーカーはEVGATVaultMarkerを、スペルはEVGAnimVaultSpellを使います。Markerは馬車のZ座標に+100.0すると丁度いいようです。
椅子に座るのはPackageのSitTargetというProcedureを使います。指定した家具を使い続けるというものです。椅子の指定方法はPO3 Papyrus ExtenderのSetLinkedRef関数を使うか、ReferenceAlias経由で指定するのがいいでしょう。
CKで配置しておいてReference IDを直指定する方法はダメです。どういうわけか、CKで事前に配置したFurnitureはゲーム内で移動できません。動的生成したFurnitureは移動できるため、内部データの管理方法が異なるのだと思われます。