忍者ブログ

方向音痴のSkyrim

PCゲーム「Skyrim」の雑多なCKいじり日記

フォロワー拡張Modの自作13【仲間割れ防止から喧嘩上等へ】

仲間割れ防止のためのなにかをしようと思ったのですが、手ごわかったです。
フレンドリーファイア防止のModなどをあれこれ参考にさせてもらったり、自分でも試したり、なぜかフォロワー皆に嫌われてしまうセロさんに悩まされたり、色々やっているうちに最初の趣旨から方向性が540度くらいずれました。


結論として至った、仲間割れ防止方法のみ先に書いておきます。
人間用フォロワー、動物用フォロワーそれぞれにScriptを設定していますが、それの「OnCombatStateChanged」のところをこんな感じに書き換えます。 参考にさせていただいたModでも"StopCombat()"で強制的に戦闘状態を解除させる処理がなされていたので、これで多分大丈夫だと思います。


フォロワーのCombatStateが変化したときに自動実行される処理です。
CombatStateは、

0:非戦闘状態
1:戦闘状態
2:索敵状態

の3種類あって、ターゲットに敵のReferenceが入るのが「1」と「2」のStateです。「0」のときはターゲットは「NONE」です。
デバッグ用のコメントを入れておいたので、Stateの遷移状態がログから確認できるかと思います。
仲間割れが発生したときは、ゲーム画面の左上にこそっとお知らせが出ます。

実際の処理は、まずターゲットが存在する場合、「相手がプレイヤーならフォロワーから外れて抗戦」という処理を先に行わせています。これでフォロワーがプレイヤーに対して怒ったとき、一方的に殺されずにすみます。Crimeファクションとの兼ね合いもあるかもしれませんが、NPCはこちらが武器を収めれば交戦状態を解いて許してくれる場合が多いです。嫌われますけど。
もしターゲットがプレイヤーでなかった時は「味方かどうか」を判断します。味方と判断されれば「仲間割れ発生」として、自分と相手の戦闘状態を強制解除します。これならバニラ枠フォロワーから敵対されても対処できます。……「OnCombatStateChanged」のイベントがきちんと実行されれば、ですが。されない時があったもので、甚だ不安です。

「味方かどうか」の判断の仕方は色々あります。ターゲットが「プレイヤーのチームメイトか」「特定のファクションに加入しているか」などを判断する関数があるので、それを使っても同じような結果が得られるかと思います。
ここでは新しいPropertyを必要としない方法をとりました。ターゲットが「自分自身と仲間関係にあるファクションに入っているか」もしくは「プレイヤーと友達以上の関係か」を判断しています。これで味方認定したら、自分の戦闘状態を解除。もしターゲットが「プレイヤーに敵対していない」のであれば、ターゲット側の戦闘状態も解除します。これだと、プレイヤーがフォロワーを攻撃して敵対してしまった時、他のフォロワーがプレイヤーを守ろうとこぞって袋叩きにいくことはないでしょう。プレイヤーと元フォロワー(敵対した時点でフォロワーから外れているはず)の喧嘩を自重しながら見守る形になります。……とりあえず、プレイヤーの友人といざこざを起こすのを避けます。

ちなみにPropertyを必要としない方法を取ったつもりでしたが、「Game.GetPlayer()」という関数をScript内で3回使ってます。CK wikiの説明を読むと、「1回しか使わないならいいけど、何回も使うならPropertyでプレイヤーのReferenceを設定した方が1000倍早い」とありました。言葉のあやにせよ、1000倍は見逃せない違いです。「Actor Property PlayerRef Auto」と設定すれば、「Auto-Fill All」ボタン一発でCKがPropertyにプレイヤーのReferenceを設定してくれるので、こちらに書き換えたほうがいいかもしれないです。3000倍処理が早くなりそう。戦闘中のScript処理は速さが命に直結しますから……。

・Combat Stateの遷移とNPCの記憶力について
NPC達はCombatStateが変わると、それまで自分が戦っていた相手を綺麗さっぱり忘れてくれるようです。そして周りに敵がいれば、改めてその敵をターゲットに取って戦いを開始します。敵対したフォロワー同士もこれに当てはまるようで、敵対は一時的なもののようです。仲間割れしている最中でもリークリングなんかが寄って来て攻撃してくると、そちらとの戦いを優先し(CombateStateが対リークリングに遷移する)、敵を倒したあとは何事もなかったかのように仲直りしてました。
仲間割れ対策で"StopCombat()"する理由がこれだと思います。

以上です。全てが終わりました。
テストが終わったら、デバッグ用メッセージを全てコメントアウトします。

これでついに、バニラのフォロワーシステムそっくりのフォロワー拡張Modができました!
傭兵達もちゃんとお金を払って雇用できます。仲間割れの心配も多分、あんまりありません。バニラ枠のフォロワーとも仲良くやれそうです。普段はセラーナさんみたいにフリーダムに振舞ってくれるし、こちらが忍べば彼らも忍び、抜刀すれば場所を空けてくれます。うまく誘導すれば、ダンジョンの一本道を先に歩かせることも可能でしょう。ファストトラベルやエリア移動についてこないこともあるけど、再ファストトラベルや待機で8割くらいはそばに来てくれます。
ずらっと書くと欠点が気になりましたが、このくらい緩い仕様のmodも手作り感があふれて温かみがあるかもしれません。修正し甲斐もあります。むしろAI PackageのFlagsとかScriptとか、修正改善だらけ……。
改善点に自分で気がつけるというのも成長の証だと思うので、今後もちょいちょい修正しつつ、このModを完成させられたらと考えています。

「フォロワークエストの自作」のCK作業日記は、ここでいったん終了。
何か間違いや気づいたことがあれば、記事を修正しておきます。

前へ | 終了

以下、備忘録を兼ねたどうでもいい苦労話です。


仲間割れ防止……。
まずは仲間割れを誘発しなければいけないので、「アイスストーム」「チェインライトニング」など比較的味方を巻き込みやすい魔法を覚えているNPCと、それらの杖を持たせたNPCをフォロワーとして用意します。フォロワー枠も4人に増やしました。
そして、狭くて敵の多い場所で戦わせることにしました。
ちょうどストームクロークで内戦を終了させたデータがあったので、ブルーパレスの例の地下室へ。
不死属性の人が多いので、十分長い間戦闘が続き、誤爆の確率も高くなるだろうと思ったのです。この時は。



薄暗かった地下室が、あっという間に眩しくなりました。
チェインライトニングがこっちにも飛んできて、敵よりもプレイヤーにチェインしている回数が多い気が……。
ファルク・ファイアビアードや衛兵も駆けつけてきましたが、どうやらプレイヤー側に助太刀しに来たようです。
これまで一般NPCは極力傷つけないプレイをしていたので、こんなに(フォロワー達が)大暴れするとぞくぞくします。



脱落者、逃亡者、死亡者が出る中、終始プレイヤーへ投降を呼びかけ続けるカイウス指揮官。ちょっとやそっとの勇気や職業意識ではここまで出来ませんよ。決して身づくろいをする雄鶏なんかじゃないですよ。
それにしても罰金安っ!
30分以上こんなバカなことをして、はたと気がつきました。



敵との戦闘がいったん終わらないと、仲間割れって起きないんじゃないかと。
カイウス指揮官のおかげでホワイトランへ高飛びできたので、仕切りなおし。
このときのScriptは、まだデバッグ用メッセージも十分用意していなかったし、敵対した相手のStopCombat処理もしていませんでした。これが次に続くテストの行き詰まりの原因にもなりました。



巨人の野営地へ。
ちょうどいい感じでアイスストームが味方を巻き込んでいます。
フォロワーには自作のNPCドヴァキン2名も入れています。氷晶、アイスブレス、ファイアブレス、ストームコール。はた迷惑なNPCにしようと思って、すべてプレイヤーへの誤爆を誘発するために覚えさせたようなものです。まさか仲間割れ防止テストで役立てる日が来ようとは……。



くだんの、セロさんが他のフォロワーに嫌われる事象発生。巨人との戦闘終了後、なぜかエランドゥルが執拗にセロを攻撃し始めました。セロにはアイスストームの杖を持たせていたので、それが誤爆したのでしょうが、エランドゥルのScriptが一切動いていないようなのです。
左上に出ているのは、セロさんが必死に自重しているメッセージ。彼の方はどんなに殴られても、戦闘を解除し続けます。戦闘が解除されると体力は自動回復するので、死にはしないのですが……。
巨人との戦闘中も、時々セロと他のフォロワー間での仲間割れが発生して戦闘を解除した知らせが出ていました。しかし戦闘が終了すると、セロさんと他のフォロワーがやたら敵対し続けるようになります。で、自重するのはいつもセロ。そしてエランドゥルがキレる確率がすこぶる高い。この二人仲が悪いのか、それともセロさんの何かがいけないのか(DLCのNPCだから?)。色々勘ぐりたくなりますが、セロを攻撃するフォロワーの「OnCombatStateChanged」が呼び出されていないのは確かなようです。



Papyrusログを見ても原因がさっぱり分かりません。これは巨人を倒した直後、エランドゥルさんがセロさんに殴りかかる直前の記録です。
「Follower01」がエランドゥル、「Follower04」がセロです。
4人そろって巨人にタゲを取った記録のあとで、「Follower01」以外のフォロワーはCombatStateが「0」に遷移しているのが分かります。「Follower01」のState遷移記録はここでおしまいになっていて、あとは延々と「Follower04」が「Follower01」に対してStopCombatしたという記録が続いています。やはりエランドゥルさんの「OnCombatStateChanged」が動いてないです。理由は分かりません。
ちなみに誰が巨人に止めを刺したのかも分かりません……。エランドゥルさんだったのかなぁ。アイスストーム、アイスブレス、ファイアブレス、ファイアボール、チェインライトニングにストームコールの落雷が飛び交う戦場で、それを目視確認するのは困難です。もうちょっと細かくログを取ればよかったですね……。
エランドゥルさん、魔法使いっぽいのに結構前に出る人だし、セロさんはどちらかと言うと距離をとって戦うので、敵対しやすいのは分かります。でもどうして迷惑ドヴァキンを差し置いてこの二人が。

とりあえずもこの件は、セロさんが悪いわけでもエランドゥルさんが短気なわけでもないということが分かりました。
そして「akTarget.StopCombat()」の一行をそっと付け加えました。片方の「OnCombatStateChanged」が動いてさえくれれば、争いが収まります。でもここまでに至ったのは後の話。途中で全然違うことをして遊んでました。

ログを見ても原因が分からず、テストプレイにも疲れてきてはじめて、妙な方向に考えが再回帰&反転しました。
それは、「穏便な方法で仲間割れを許可する」です。要するに、武器・魔法の使用を禁止して純粋な殴り合いをさせるというもの。命をかけた戦闘中、下手な狙いの攻撃で何度も誤爆を受けたら、誰だってプチッとなるはずです。戦闘が終わったら、ツカツカ近づいていってガツンとやりたくなるはずです。仲間割れが防止できないなら、思う存分喧嘩しろ!という、まあ……ヤケです。



「喧嘩上等」のAI PackageをCombat Overrideとして作成しました。Combat Styleには「csUnarmedOnly」というのを選択します。このAI Packageが動いている間は、このCombat StyleがNPCに適用されます。
「csUnarmedOnly」は、同胞団のンジャダとアシスの殴り合いイベントで使われています。素手攻撃以外を全て禁止するCombat Styleなので、喧嘩に最適!



……とか思ってたら、よく見ると魔法の杖を使う可能性があります。
だめだ。これ使っちゃいけない。



「csUnarmedOnly」をコピーして、「本当に素手だけ」の自作Combat Styleを作成し、こちらを適用することにしました。
もっとも喧嘩相手が重装備に適正のある、性能のいい重装篭手を装備したパーク持ち高レベルカジートとかだったら洒落にならないです。そこは覚悟した上での、「仲間割れ許可」です。



AI PackageのConditions。
Combat Overrideのみで使用できる「Combat Target」というのを使用して、戦っている相手が味方である時のみPackageが有効になるようにします。
とりあえずはテストなので、簡単に設定。
Flagsは、バニラFollower用のCombatOverride Packageを参考にして設定しています。念を入れて「Weapons Unequipped」チェックも入れました。



基本的にOverride系AI Packageは、FormListに登録してから使います。



自作クエストのFollower AliasにFormListを設定。
殴り合いは人間だけでいいので、人間フォロワーAliasのみに設定しています。

Combat Overrideを使って戦闘中のフォロワーをあれこれ弄り倒してやろう。
そう思って、下地となるシンプルなフォロワー拡張Modの自作を始めたわけですが、まさかこんな不本意な形で一足早くCombat Overrideを用意することになろうとは、夢にも思いませんでした。

CombatOverride Packageは、「OnCombatStateChanged」で誰かと戦闘状態になるたび、毎回「EvaluatePackage()」でAI Packageを再計算させないとうまく動作してくれないようです。味方と敵対した後で「EvaluatePackage()」してもPackageの起動がうまくいかないか間に合わないので、相手フォロワーが斬り殺されてしまいます。相手フォロワーに対しては、仲間割れが発生した時点で「akTarget.EvaluatePackage()」してCombatOverride Packageを強制的に呼び出します。これも間に合わないかもしれないのは妥協してます。



ブリストルバック洞窟で動作テスト。ある程度狭いし敵も多いので、誤爆テストに最適です。
メンバーは、因縁のセロさんと、ドヴァキン2名、炎のマントを使う自作フォロワー(セロさんとほぼ同じ挙動)。セロの代わりにマーキュリオを連れて行ったりもして、洞窟を20周くらいしました。
かなり激しい爆発や一本道での掃討アイスストームもあるのですが、意外なことに仲間割れ自体がそんなに発生しません。フォロワーファクション同士の関係をAllyにしているので、もしかしたらそれが結構効いているのかも。



待望の殴り合い発生。炎のマントのダメージも入っているようです。マーキュリオさんが色々と不利だ。
殴り合いの最中に敵が近づくと、素手のまま応戦することがあります。これは敵を倒すとすぐ直るので、武器を取り出す暇がなかったんだなという程度で受け入れられる範囲かと思います。



見づらいですが、相手方のCombatOverride Package呼び出しが間に合わなかったか失敗した例。体力吸収の付いた黒檀の剣で斬りかかられています。相手がバニラ枠のフォロワーであった場合も、殴り合い用CombatOverrideの設定そのものがないので武器や魔法で攻撃されてしまいます。
こういった刃物沙汰を想定して、喧嘩は5秒間だけ許可。生き抜けば仲直りできます。

画面右側に写っている氷の塊は、ドヴァキン姐さんの氷晶シャウトで固まったプレイヤーとフォロワー。



生き抜くことができなかった人。二人のフォロワーに連続で殴られて倒れました。ライトニングボルトも結構誤爆率高いですからね……。時々サーチライトみたいに振り回すし。

……おかしいな。Protect属性ついてるはずなのに、NPC同士の戦いで止め刺されるって。PCと敵対している相手については、フォロワーはProtect属性を無視して止めを刺すようなのですが。PCの敵かどうかに関わらず、チームメイト化してると属性無視をするのかな。フォロワーが他のNPCと決定的に違うのは「SetPlayerTeammate」されていることだと思うので。
試しに味方と戦闘状態になったとき、チームメイト化をはずした上で同士討ちを許可する処理に変えたところ、相手が膝をついたら戦闘状態を解きました。チームメイト化していると、敵のProtect属性を無視すると考えてよさそうです。

フォロワー同士で喧嘩が起きると、正直かなり面倒だし不便です。でもこれはこれで人間くさくていいかと感じました。後でもう少し手を入れて、仲間割れでは死なないようにしてあげたいなぁ。
ここまで遊んで、ようやく自分が仲間割れ防止機能を作ろうとしていたことを思い出した次第です。


使用したScript。「Actor Property PlayerRef Auto」を設定し、デバッグ用メッセージにSKSEの関数を使用しています。


前へ | 終了
PR

Author

UNI
Skyrimで遊ぶのも、CKで改造するのも好きなファンタジー好きです。
戦闘苦手で難易度は基本EASY、慣れてもNORMAL程度。 アンデッド恐怖症なので、ノルド遺跡探索が辛い……。

ブログ内検索

最新コメント

[11/12 fighf]
[11/11 AllicebeLype]
[11/11 コング]
[11/10 chomechome-X]
[11/05 UNPおじさん]