プレイ中に導入・更新可能なSkyrim MODを作るには
プレイ中の互換性の重要性
Skyrimのプレイヤーは、1つのセーブデータに数百時間、数千時間をかけることさえある、その熱心さで知られています。そのようなプレイヤーに、あなたのMODを体験するため、あるいはアップデートのために、新規ゲームを始めることを要求することは、大きな障害となりかねません。ユーザーの視点から見ると、最初からやり直すことは、数え切れないほどのプレイ時間の損失を意味し、場合によってはあなたのMODを完全に諦めてしまうことにもなりかねません。
このガイドは、特にCreation KitとMOD制作の基本知識を持つMOD制作者向けに書かれています。ここでは、MODをプレイ中にインストールまたは更新できるようにするためのテクニックを実装する方法を探り、ユーザーにとってよりスムーズで楽しい体験を保証します。
アップデートとインストールへの対応
プレイ中の互換性を実現するための鍵は、MODの更新時や初回インストール時に、スクリプト、クエスト、オブジェクト参照をどのように管理するかを理解することです。これらのシナリオは同じ原則を共有しているため、ここでは一緒に説明します。
タイミングが全て:ロジックの実行
-
OnInitイベント: 簡単な方法は、アップデート/インストール専用に設計された新しいクエスト内で
OnInit
関数を使用することです。このクエストは、Creation Kitのクエストデータタブで「ゲーム開始時に有効」に設定する必要があります。スクリプトタブからこのクエストにスクリプトを添付し、OnInit
関数内にアップデート/インストールのコードを記述します。 -
OnPlayerLoadGameイベント: アップデートの場合、
OnPlayerLoadGame
イベントが代替手段となります。エイリアスタブでエイリアスを作成し、それをプレイヤーを参照するように強制し、このエイリアスにスクリプト(ReferenceAliasスクリプトを拡張したもの)を添付します。OnPlayerLoadGame
関数内にアップデートのロジックを実装します。このイベントは、新しいクエストの初期化時ではなく、セーブデータのロード時にのみトリガーされることに注意してください。ただし、OnInit
はこのエイリアススクリプトのクエスト開始時にも実行されます。 -
OnCellAttachイベント:
GetDistance
やFindClosestReferenceOfAnyTypeInListFromRef
など、一部の関数はロードされたObjectReferenceを必要とします。アップデート/インストールのロジックがこれらに依存する場合は、OnCellAttach
関数を使用します。
スクリプトの謎を解く
スクリプトは、プレイ中の互換性を懸念するMOD制作者にとって、しばしば不安の種となります。しかし、スクリプトがセーブ処理中にアクティブに実行されている場合(これはまれです)を除き、そのコードと実行状態は保存されません。スクリプトは通常、特にRegisterForSingleUpdate
とOnUpdate
を使用してUtility.Wait
の代わりに長い遅延を実装している場合は、すぐに実行されます。
主な懸念は、保存されるスクリプトのプロパティとインスタンス変数にあります。幸いなことに、これらは管理可能です。
-
プロパティ: Papyrusを使用して、値を直接目的の状態に設定します。
-
インスタンス変数: これらはスクリプトにプライベートであるため、更新するためのセッター関数を作成します。
int myInstanceVar = 5 Function SetMyInstanceVar(int newValue) myInstanceVar = newValue EndFunction
重要なのは、すでに初期化されたスクリプトに新しく追加されたプロパティは、プラグインで指定された値に自動的にデフォルト設定されるため、既存のプロパティを調整するだけでよいということです。
クエストの操作
クエストが実行されると(ジャーナルに表示されるだけでなく)、そのステージ、スクリプトのプロパティ、エイリアスは固定されます。これを処理する方法は次のとおりです。
-
エイリアス:
ForceRefTo
関数を使用して簡単に更新できます。アップデート/インストールのロジックで新しい参照をスクリプトプロパティとして追加し、ForceRefTo
を使用してエイリアスをその参照に向けます。 -
クエストステージ:
オブジェクト参照の管理
ゲームの世界を変更するMODは、オブジェクトの配置の競合を引き起こす可能性があり、多くの場合、作者は新しいセーブデータを要求することになります。これは、永続的な参照の位置が保存されるためです。
永続的なオブジェクト参照だけが問題であることを覚えておいてください。一時的なオブジェクトは保存されないため、新しい位置に自動的に更新されます。
-
移動可能なオブジェクト: アクティベーター、コンテナ、可動スタティック、マーカーなど、ほとんどの永続的なオブジェクトは、スクリプトを使用して移動できます。
MoveToMyEditorLocation
関数は、このために特に役立ちます。 -
移動できないオブジェクト: 木、植物、スタティック、家具は、スクリプトで移動できません。解決策をいくつか紹介します。
- 無効化と置換: オブジェクトが他のMODで使用されていない場合は、古いオブジェクトを無効化し、目的の場所に新しいオブジェクトを追加します。これらのオブジェクトを参照するクエストエイリアスまたはスクリプトプロパティが適切に更新されていることを確認してください。
- Save Unbakerの必須化: Save Unbaker MODを必須MODとして追加します。このツールは、これらのオブジェクトを自動的に新しい位置に移動します。
その他の永続的なレコード
セーブデータに永続化されるその他のレコードを以下に示します。
-
派閥ランク:
SetFactionRank
、AddToFaction
、RemoveFromFaction
で変更可能です。 -
関係ランク:
SetRelationshipRank
を使用して調整できます。 -
NPCの服装:
SetOutfit
で変更可能です。
例:遡及的なアップデートスクリプト
ScriptName RetroactiveFixAlias Extends ReferenceAlias
MyQuestScript Property myQuest Auto
ObjectReference Property myQuestProperty1Ref Auto
ObjectReference Property myQuestProperty2Ref Auto
ReferenceAlias Property myAlias1 Auto
ReferenceAlias Property myAlias2 Auto
ObjectReference Property myAlias1Ref Auto
ObjectReference Property myAlias2Ref Auto
ObjectReference Property myRef1 Auto
ObjectReference Property myRef2 Auto
ObjectReference Property myActor1 Auto
Outfit Property myActor1Outfit Auto
int currentVersion = -1
Event OnInit()
HandleInstallOrUpdates()
EndEvent
Event OnPlayerLoadGame()
HandleInstallOrUpdates()
EndEvent
Function HandleInstallOrUpdates()
If currentVersion != 2
myQuest.myQuestProperty1 = myQuestProperty1Ref
myQuest.myQuestProperty2 = myQuestProperty2Ref
myAlias1.ForceRefTo(myAlias1Ref)
myAlias2.ForceRefTo(myAlias2Ref)
myRef1.MoveToMyEditorLocation()
myRef2.MoveToMyEditorLocation()
myActor1.SetOutfit(myActor1Outfit)
currentVersion = 2
EndIf
EndFunction
例:セルロード後のObjectReferenceの修正
ScriptName RetroactiveFixObjectReference extends ObjectReference
int currentVersion = -1
ObjectReference Property myRef Auto
FormList Property myRefTypes Auto
Event OnInit()
; バージョン2で初期化されているため、修正は不要
currentVersion = 2
EndEvent
Event OnCellAttach()
If currentVersion != 2
myRef = Game.FindClosestReferenceOfAnyTypeInListFromRef(myRefTypes, self, 100.0)
currentVersion = 2
EndIf
EndEvent
結論
このガイドでは、すべてのシナリオを網羅しているわけではありませんが、Skyrim MODをよりアクセスしやすく、ユーザーフレンドリーにするための確固たる基盤を提供しています。完璧なプレイ中の互換性を実現することは難しい場合がありますが、その方向への小さな一歩が、ユーザーの体験を大幅に向上させる可能性があることを忘れないでください。