第八章(´・ω・`)おばあちゃん、武器クラスとプレイヤーモデルの関係について考えるわよ☆



・どう見られてるの?

第六章で作成したマグナムのクローン武器「ゲロ銃」、 クライアント視点の武器ビューモデルに関しては特に問題がないことは第七章でわかりました。
しかし、ゲロ銃使用中のあなたを他のプレイヤーが見た場合、どんなふうに見えるんでしょうね?

・Botを足してみよう

さて、とりあえずserver.dllをビルドするための hl_sdkプロジェクト(第五章でソリューションを分離してからhlhl_sdkに名前が変わっています) へ2つファイルを足してもらいます。

C:\Bodycon\src\dlls\hl2mp_dll

上記フォルダ下の

hl2mp_bot_temp.cpp
hl2mp_bot_temp.h


この2つのファイルをVC++のソリューションエクスプローラのツリー上で以下のパスに該当するフォルダ下へドラッグ&ドロップします。
hl_sdk\Source Files\HL2MP

(´・ω・`)追加で〜きた♪

次は以下のように4箇所だけコードを書き換えましょう。

☆追加したばかりのhl2mp_bot_temp.cppを開き、 24行目で以下の赤く記した部分の書き換えを行います。
void ClientPutInServer( edict_t *pEdict, const char *playername );
void Bot_Think( CHL2MP_Player *pBot );

#ifdef _BOT_IMPL

hl2mp_client.cpp(ソリューションエクスプローラ上でhl2mp_bot_temp.cppの2つ下にあるよ)の 188行目で以下の赤く記した部分の書き換えを行います。
#ifdef _BOT_IMPL
	extern void Bot_RunAll();
	Bot_RunAll();
#endif

hl2mp_gamerules.cpp(ソリューションエクスプローラ上でhl2mp_client.cppの2つ下にあるよ)の 33行目で以下の赤く記した部分の書き換えを行います。
#ifdef _BOT_IMPL
	#include "hl2mp_bot_temp.h"
#endif

☆同じくhl2mp_gamerules.cppの831行目で以下の赤く記した部分の書き換えを行います。
#ifdef _BOT_IMPL

	// Handler for the "bot" command.
	void Bot_f()


書き換えましたか?今度はプロジェクトのプロパティページを開いて(第三章参照)、 元から書いてある設定へ更にプリプロセッサ定義の記述を追加します。
・構成プロパティ−>C/C++−>コマンドライン
[追加のオプション]内に以下の赤く示した記述を追加
/D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "_CRTIMP=" /D "_CONST_RETURN=" /D "_BOT_IMPL"



上記が完了したらF7キーを押してserver.dllをビルドしましょう。

・ウン命の出逢い

ゲームを起動する前にテスト用の狭いマップ

unko_test.bsp

こいつをダウンロードしてMODのマップフォルダ下

C:\Program Files\Valve\Steam\SteamApps\SourceMods\Bodycon\maps

にブチ込みます。
ブチ込んだらこのマップでゲームをスタート!

(;゚Д゚)鬼ダサイ駄目マップキタコレ!!

コンソールから以下のコマンドを実行します。
sv_cheats 1
bot_attack 0
bot_zombie 1
bot_mimic_yaw_offset -90
bot

すると・・・


(´・ω・`)ズコーン!ビックリしたなあ、もう!

更にコンソールから以下のコマンドを実行したら上下左右向いたり、跳んだり、しゃがんだりしてみましょう。
bot_mimic 1



(#゚Д゚)てめえ、俺の真似すんじゃねえバッキャロー!!


・あれれ?

Botがモノマネモードに入ったら、ゲロ銃を選択してみます。
時々Botがゴネて武器を切り替えない時がありますが、しつこく選択しなおすとBotが根負けして ゲロ銃を選択してくれます(他の武器に切り替える場合も同様です)。

Botがゲロ銃を選択したらこのコマンドでモノマネモードを解除して近づいてみます。
bot_mimic 0

・・・あれれ?


(´・ω・`)なんか、その持ち方ヤバくない?手首だいじょぶ?


ちなみに、こっちがガッポイライフル(AR2)の正しい持ち方。(モノマネモードの時は impulse 101 コマンドでBotにも武器、弾薬が支給されるので、色々遊んでみましょう)


・はやく直さないと

早急にこの問題を解決しなければ愛すべきガッポイの手首が折れてしまいます。単純に武器スクリプトファイル weapon_gero.txtのワールドモデル指定を
weapon_gero.txtの一部
	"playermodel"	"models/weapons/w_irifle.mdl"
こう書き換えただけでは駄目だったんでしょうか?

・・・そのとおり、駄目なんです。

ソースコード上のここに問題があります。
weapon_gero.cppの89〜106行目
#ifndef CLIENT_DLL
// 武器携行時の挙動上書きリスト定義
acttable_t CWeaponGero::m_acttable[] = 
{
	{ ACT_HL2MP_IDLE,			ACT_HL2MP_IDLE_PISTOL,		false },
	{ ACT_HL2MP_RUN,			ACT_HL2MP_RUN_PISTOL,			false },
	{ ACT_HL2MP_IDLE_CROUCH,		ACT_HL2MP_IDLE_CROUCH_PISTOL,		false },
	{ ACT_HL2MP_WALK_CROUCH,		ACT_HL2MP_WALK_CROUCH_PISTOL,		false },
	{ ACT_HL2MP_GESTURE_RANGE_ATTACK,	ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL,	false },
	{ ACT_HL2MP_GESTURE_RELOAD,		ACT_HL2MP_GESTURE_RELOAD_PISTOL,	false },
	{ ACT_HL2MP_JUMP,			ACT_HL2MP_JUMP_PISTOL,		false },
	{ ACT_RANGE_ATTACK1,			ACT_RANGE_ATTACK_PISTOL,		false },
};

// 武器携行時の挙動リスト登録
IMPLEMENT_ACTTABLE( CWeaponGero );

#endif

武器クラスのm_acttableメンバ変数には
{[基本動作のアクティビティ], [基本動作を上書きするアクティビティ], [マルチプレイに関係なさそうなんで無視]}
この組み合わせを単位として、武器を持った状態でのプレイヤーのアニメーションを決定するために 最低限7つの要素を用意しなければなりません。逆にこれを正しく指定しさえすればあとはValve提供の既存クラスが うまいことやってくれるので他に気にすることは何もありません。
ACT_HL2MP_IDLE 立ちのアイドル状態
ACT_HL2MP_RUN 立って走ってる状態
ACT_HL2MP_IDLE_CROUCH しゃがみでのアイドル状態
ACT_HL2MP_WALK_CROUCH しゃがんで歩いてる状態
ACT_HL2MP_GESTURE_RANGE_ATTACK 攻撃動作
ACT_HL2MP_GESTURE_RELOAD 武器リロード時の動作
ACT_HL2MP_JUMP ジャンプ動作
(※)ACT_RANGE_ATTACK1は用意してもしなくともマルチプレイには影響ないようです。

(#゚Д゚)んじゃあゲロ銃クラスのm_acttableメンバの内容を ガッポイライフルのソースweapon_ar2.cppと同じように書き換えりゃ終わりじゃねーかバロー

確かにそれで正解なんですが、もうちょっと細かく探ってみましょう。

ゲロ銃は基本動作を以下のように上書きしています(ACT_RANGE_ATTACK1に対するACT_RANGE_ATTACK_PISTOLの指定はシカト、どうでもいい)
  • ACT_HL2MP_IDLE→ACT_HL2MP_IDLE_PISTOL
  • ACT_HL2MP_RUN→ACT_HL2MP_RUN_PISTOL
  • ACT_HL2MP_IDLE_CROUCH→ACT_HL2MP_IDLE_CROUCH_PISTOL
  • ACT_HL2MP_WALK_CROUCH→ACT_HL2MP_WALK_CROUCH_PISTOL
  • ACT_HL2MP_GESTURE_RANGE_ATTACK→ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL
  • ACT_HL2MP_GESTURE_RELOAD→ACT_HL2MP_GESTURE_RELOAD_PISTOL
  • ACT_HL2MP_JUMP→ACT_HL2MP_JUMP_PISTOL

  • これらのアクティビティはプレイヤーのモデルとどんな関係にあるんでしょうか?

    それはプレイヤーのモデルのQCファイルにヒントがあるかもしれません。以下のファイルを開いてみましょう。

    C:\Program Files\Valve\Steam\SteamApps\××××\sourcesdk_content\hl2mp\modelsrc\Player\player_anims.qci

    ・・・と思ったらQCIファイルっすか?QCのインクルードファイルのような物と思っちゃっていいのかな?
    それはさておき、このファイルの中でゲロ銃使用中のプレイヤーが各動作のアニメーションに使用する アクティビティに割り当てられたシーケンスを抜き出してみまいた。表示の都合上、改行してる場所もありますが、 実際のQCでこんな改行は認められていないはずです。
    player_anims.qciから抜粋
    $makeidle idle_pistol "..\humans_sdk\male_animations\WeaponAnims_Shared\Pistol_aim_matrix"
    	4 weapons_Pistol_aim_matrix ACT_HL2MP_IDLE_PISTOL 1
    $makematchrun run_pistol "..\police_xsi\RunN_aim_pistol"
    	0 police_WalkN_pistol_aim_matrix ACT_HL2MP_RUN_PISTOL 1
    $makecidle cidle_pistol "HL2DM_crouch_aim_pistol" 4 HL2DM_crouch_aim_pistol ACT_HL2MP_IDLE_CROUCH_PISTOL 1
    $makecwalk cwalk_pistol "HL2DM_crouch_aim_pistol" 4 HL2DM_crouch_aim_pistol ACT_HL2MP_WALK_CROUCH_PISTOL 1
    $makerange range_pistol "..\police_xsi\Pistol_shoot_1" 0 ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL 1
    $makereload reload_pistol "..\police_xsi\Pistol_reload" ACT_HL2MP_GESTURE_RELOAD_PISTOL 1
    $makejump jump_pistol "HL2DM_crouch_aim_pistol" 4 ACT_HL2MP_JUMP_PISTOL 1
    
    武器のビューモデル同様、赤いとこはアクティビティ名称、セクシャルバイオレットは SourceSDKのモデルビューアで表示されるシーケンスの名称、そしてウンコ色のとこが SMDファイル名(拡張子なし)。先頭の$〜の名前がそれぞれ違いますが、これは恐らくマクロの名前なんじゃないの〜?知らんけど。
    これを見る限り、モデルデータの中からアニメーションの再生ポインタを見つける手順は武器のビューモデルと同じと考えてよいでしょう。

    各動作をSDKのModelViewerで見るとゲロ銃を使う際のプレイヤーの動作はこんなふうに変更すると うまく行くと思うニャー(=・ω・=)。
  • idle_pistolidle_ar2
  • run_pistolrun_ar2
  • cidle_pistolcidle_ar2
  • cwalk_pistolcwalk_ar2
  • range_pistolrange_ar2
  • reload_pistolreload_ar2
  • jump_pistoljump_ar2


  • で、その名前に該当する物をplayer_anims.qciから探すと
    player_anims.qciから再度抜粋
    $makeidle idle_ar2 "..\combine_soldier_xsi\Hold_AR2" 0 soldier_Aim_9_directions ACT_HL2MP_IDLE_AR2 1
    $makematchrun run_ar2 "..\combine_soldier_xsi\Hold_AR2" 0 soldier_Aim_9_directions ACT_HL2MP_RUN_AR2 1
    $makecidle cidle_ar2 "..\combine_soldier_xsi\Shoot_AR2_crouch"
    	0 soldier_Crouch_aim_9_directions ACT_HL2MP_IDLE_CROUCH_AR2 1
    $makecwalk cwalk_ar2 "..\combine_soldier_xsi\Shoot_AR2_crouch"
    	0 soldier_Crouch_aim_9_directions ACT_HL2MP_WALK_CROUCH_AR2 1
    $makerange range_ar2 "..\combine_soldier_xsi\Shoot_AR2" 0 ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2 1
    $makereload reload_ar2 "..\combine_soldier_xsi\Reload_standing" ACT_HL2MP_GESTURE_RELOAD_AR2 1
    $makejump jump_ar2 "..\combine_soldier_xsi\Shoot_AR2_crouch" 0 ACT_HL2MP_JUMP_AR2 1
    


    つまりゲロ銃で基本動作に上書きするアクティビティはこう変更すればいいんだニャー(=・ω・=)。
  • ACT_HL2MP_IDLE_PISTOLACT_HL2MP_IDLE_AR2
  • ACT_HL2MP_RUN_PISTOLACT_HL2MP_RUN_AR2
  • ACT_HL2MP_IDLE_CROUCH_PISTOLACT_HL2MP_IDLE_CROUCH_AR2
  • ACT_HL2MP_WALK_CROUCH_PISTOLACT_HL2MP_WALK_CROUCH_AR2
  • ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOLACT_HL2MP_GESTURE_RANGE_ATTACK_AR2
  • ACT_HL2MP_GESTURE_RELOAD_PISTOLACT_HL2MP_GESTURE_RELOAD_AR2
  • ACT_HL2MP_JUMP_PISTOLACT_HL2MP_JUMP_AR2


  • というわけでソースコードで問題のある個所を赤く示したように修正してserver.dllをビルドします。
    weapon_gero.cppの89〜106行目
    #ifndef CLIENT_DLL
    // 武器携行時の挙動上書きリスト定義
    acttable_t CWeaponGero::m_acttable[] = 
    {
    	{ ACT_HL2MP_IDLE,			ACT_HL2MP_IDLE_AR2,			false },
    	{ ACT_HL2MP_RUN,			ACT_HL2MP_RUN_AR2,			false },
    	{ ACT_HL2MP_IDLE_CROUCH,		ACT_HL2MP_IDLE_CROUCH_AR2,		false },
    	{ ACT_HL2MP_WALK_CROUCH,		ACT_HL2MP_WALK_CROUCH_AR2,		false },
    	{ ACT_HL2MP_GESTURE_RANGE_ATTACK,	ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2,	false },
    	{ ACT_HL2MP_GESTURE_RELOAD,		ACT_HL2MP_GESTURE_RELOAD_AR2,		false },
    	{ ACT_HL2MP_JUMP,			ACT_HL2MP_JUMP_AR2,			false },
    	{ ACT_RANGE_ATTACK1,			ACT_RANGE_ATTACK_PISTOL,		false },
    };
    
    // 武器携行時の挙動リスト登録
    IMPLEMENT_ACTTABLE( CWeaponGero );
    
    #endif
    


    ・ハッピーエンド

    もっかいゲームを起動して確認してみましょう。


    (´・ω・`)ひゃっほう!その持ち方が正解だぜ!


    (´・ω・`)バーン!バーン!

    (※実際は bot_zombie 0 に戻してやらないとバンバンできません)

    (´・ω・`)つ次へ