今さら感がすごい内容ですが、NPCのステータスを変更する方法を書いてみました。そこまで詳しく突っ込んだ内容ではなく、既存の設定をちょっと変えたいんだよなー というときに見ることを想定しています。
フォロワーを調整したかったらこの記事を読んでね。と、フォロワー拡張MODを公開している私が逃げ場とするために書いてみた。
1. 不死化させる
フォロワー拡張MODで良く言われるやつ。まぁ、お気に入りのキャラクターに死んでほしくないっていう気持ちはすごくわかりまする。
1-1. コンソール
ゲーム内で、コンソールコマンドから不死化させる方法です。簡単確実もうこれでOK。
SetEssential BaseID
BaseID の部分には、対象のNPCの BaseID を入力します。RefID ではない点に注意。BaseID は、コンソール画面で対象をクリックすればバニラでも表示されたような気がする(されない?)。どちらにせよ、LEなら Mfg Console、SEなら opparco mfg Command for SSE などのコンソール拡張MODを入れておけば表示されます。
1-2. esp
ニューゲームのたびに複数のNPCを不死化しているようなら、esp でパッチを作成してしまった方が楽です。Actors > Actor の中から対象のNPCを表示して、左端にある Essential (不死属性) にチェックを入れればOK。xEdit での変更箇所がわかるなら、そちらの方が早いです。
1-3. Papyrus スクリプト
スクリプトでも不死化できます。
ActorBase.SetEssential()
Actor でなく ActorBase に対して関数を当てます。Actor に当てたいときは、Actor.GetActorBase().SetEssential() という記述になります。
対象のNPCが Protected (保護属性) のフラグを持っていた場合、それは外されます。逆に、ActorBase.SetProtected() を当てると、Essential が外れて Protected になります。
2. プレイヤーレベルに同期させる
フォロワーはもともとプレイヤーレベルに同期しますが、上限が設定されていることもあるので、それを解除する方法です。
2-1. コンソール
コンソール画面で対象のNPCをクリックしてから以下のコマンドを入力すると、上限なしでレベル同期させられます。数値の細かいことは気にする必要なし。一応最後の数値が上限値で、0 だと無制限になります。
SetLevel 1000 0 1 0
2-2. esp
esp では、Actor の Stats タブにある Leveling Data > Calc Max でレベル上限を設定します。ここを「0」にすると、上限なしになります。その上の PC Level Mult がレベル同期のフラグですが、フォロワーならもともとチェックされているでしょう。
2-3. Papyrus スクリプト
なぜか、Papyrus スクリプトにはNPCのレベルを変更する関数がありません。そのため、スクリプトからコンソールコマンドを発動できるSKSEプラグインが必要になります。LEでは ConsoleUtil、SEでは ConsoleUtilSSE などがあります。
それらのMODが別途必要になるためユーザーさんの手間が増えてしまうんですが、SKSEプラグインの作成は私にもさっぱりわかりませんので、これは仕方ないですね。ConsoleUtil が導入されている環境なら、以下のようなスクリプトでコンソールコマンドを発動させられます。
ConsoleUtil.SetSelectedReference(Actor) ; Actor に対象とするNPCを入れる
ConsoleUtil.ExecuteCommand("SetLevel 1000 0 1 0")
3. 体力値を増減させる
体力値は1つの例ですが、いわゆる Actor Value を変更する方法です。体力で説明するのが一番理解が深まりそうなので、これでいきます。値がどのように決定されているかを知らないとわけわかんないですから、これだけは esp を先に挙げます。
3-1. esp
体力は、簡単に言うと 基本値 + オフセット値 = トータル値 で計算されます。トータル値が、実際に使用される体力です。基本値はレベルアップに応じて再計算されますが、オフセット値は固定値です。というところまで理解できれば充分ですので次の項目へどうぞ。(え?)
詳しく知りたいというマニアックな方のために、以下に計算方法を書いておきます。情報源は CreationKit Wiki の Stats と Class。
Actor の Stats タブには Health Offset と Base Health という項目があり(上図参照)、それぞれオフセット値とレベル1のときの基本値とを表しています。オフセット値は固定で加算される数値ですから、特に難しいことはありません。
基本値は、レベルアップに応じて増加します。それを決めているのが同じ Stats タブの Class という項目で、これは Character > Class で定義されています。
Attribute Weights に Health / Stamina / Magicka の数値を入れる欄があり、これは割合を示しています。NPCというのはレベルアップごとに10ポイントを獲得するようになっていて、上記の例だと体力に 10 * (2/6) = 3.3、スタミナに 10 * (4/6) = 6.6 ポイント加算されることになります。さらに、体力のみ、ボーナスポイントとして5ポイント加算されます。
これらの設定から、ファエンダルさんがレベル6のときの体力は、以下のように計算されます。
50 [レベル1の基本値] + {10 [ポイント] * (2/6) [Classの割合] + 5 [ボーナス]} * 5 [レベル上昇] + 0 [オフセット値] = 91.66 ≒ 92
…細かい! けど Calculated Health に自動で計算してくれるから大丈夫!
ちなみにレベルアップで獲得するポイントは、Game Settings の iAVDhmsLevelUp で設定されており、デフォルトは 10 です。ボーナスは fNPCHealthLevelBonus で、デフォルトは 5.0 です。
3-2. コンソール
基本値 + オフセット値 ということがわかったら、実際にコンソールで体力を変化させてみましょう。
まずは基本値の変更からやってみます。コンソールで対象のNPCをクリックしてから、以下のコマンドを入力します。ここでは、例として基本値を 300 に変更してみます。
SetAV Health 300
この変更は、次のレベルアップの時点まで有効です。レベルアップすると esp の設定に従って再計算され、変更は無効化されます。
次に、オフセット値を変更してみます。例として 50 増やしてみます。
ModAV Health 50
オフセット値は基本値に加算されますから、SetAV で 300 を指定して ModAV で 50 を指定すると、トータル値は 350 となります。オフセット値は永続的な固定値として扱われますので、次にレベルアップしたときは基本値のみが再計算され、そこに 50 加算されることになります。
オフセット値の変更には、もう1つの方法があります。トータル値を指定することによってオフセット値を自動計算させる方法です。
ForceAV Health 350
こうすると、基本値が 300 だった場合には オフセット値が 50 として設定されます。この場合も、レベルアップでオフセット値が変化することはありません。
以上を見ると自由自在に体力をコントロールできそうですが、困るのはコンソールから基本値やオフセット値を知る方法がないことです。GetAV Health というコマンドはあるものの、これはトータル値を取得しますのであまり意味がありません。
いろいろと値をいじってしまってわからなくなったら、CKを使ってそのレベルの基本値を計算し、実際の体力との差異をオフセット値と考えて調整することになります。 ModAV は現在のオフセット値に対して加算減算をするコマンドで、マイナスの値でも指定することができます。
3-3. Papyrus スクリプト
スクリプトでも、基本値とオフセット値の考え方は変わりません。Actor Value のページでは Base Actor Value と Permanent Modifier として書かれています。
スクリプトを書くときに注意することは、対象とする Actor Value において、基本値とオフセット値がどのように使われているかをきちんと調べることです。体力であれば基本値とオフセット値の組み合わせですが、基本値が 0 で、オフセット値のみでコントロールされるものもあります。
基本値 (Base Actor Value) を変更するには、以下のような関数を使います。
Actor.SetActorValue("Health", 300)
これで体力の基本値が 300 になります。余談ですが、スクリプトを翻訳しようとしてこの Health という文字列を 体力 とかにすると、当然ながらその部分は動きません。
オフセット値 (Permanent Modifier) の変更もできます。
Actor.ModActorValue("Health", 50)
オフセット値を 50 に設定したので、レベルアップに関係なく常時 50 加算されるようになります。
また、トータル値を指定してオフセット値を自動計算させることもできます。
Actor.ForceActorValue("Health", 350)
基本値が 300 だった場合には、レベルアップに関係なく常時 50 加算されるようになります。
スクリプトでは、基本値を取得する関数があります。
Int intHealth = Actor.GetBaseActorValue("Health")
返り値は Int 型です。これと GetActorValue() を使えば、オフセット値も計算することができそうですね。
以上です。よーしこれでもう安心。のんびりと Anniversary Edition を待つことにします。公式サイト見るとSEのアップグレードとか書いてあるんだけど、どんな構造なんでしょうね。LEからSEみたいな別物扱いという感じではないのかな。
ところでどうでもいいことなんですけど、私この前ワクチン打ったんですよ。その日のうちは元気で、深夜になってから38度の熱が出ました。歯が震えて起きちゃったんですが、眠いから寝る!という強い意志で無理やり寝て、次の日は万能薬イブA錠を飲みまくって耐えました。だるくてスカイリムが1時間しかできなかったので皆さんもご注意を。あ、ワクチンは任意ですよ。事情があって打ったけど、ゲームできなくなるという副作用は困るよね。