jajiman05

[flv:http://freeman.media.t-kougei.ac.jp/~nagae/hl2/flv/jajiman05.flv http://www4.media.t-kougei.ac.jp/~nagae/wp-content/uploads/2008/11/jajimen05_0001.jpg 480 320]

モデリングはだいたいわかってきたので、modで自作モデルを動かすテスト。 source sdkでcreate a modとやると空のmodができる。 仮にこのmodをpooとする。 pooにはマップも何もないので(mapsrcもmodelsrcもmaterialsrcも空)、 sourcesdkでengine versionをhalf-life2 episode1とかにして、 Current gameをpooにして、 hammer editorを立ち上げて、 よそのsourcesdk_content\hl2\mapsrcなどからsdk_d1_trainstation_01.vmfなど持ってきて、 コンパイルしてマップを作る。

自分のモデルやテクスチャもCurrent gameをpooにした状態でstudiomdl、vtexなどで コンパイルする。 eyeball_l.vmtとかeyeball_l.vtfとかpupil_l.vmtなどはやはり C:\Program Files\Steam\steamapps\SourceMods\poo\materials\SDK\Models\Humans\Male には存在しないのでしかるべき場所によそからコピーしておく。

d1_trainstation_01というのは初代half-life2の一番最初のチャプター。 この中に出てくる市民のモデルは男も女も共通でnpc_citizenというものなのだが、 これらをまるごと自分のモデルjajiman05に置き換えようと思った。 最初はsdk_d1_trainstation_01.vmfのnpc_citizenを一つ一つjajiman05に置き換えてみたが、 うまくいくやつもあるがいかないやつもある。

それで、pooのserver.dllをビルドするときに、 server_hl2\Source Files\HL2 DLL\npc_citizen17.cpp というのがあるのだが、 その765行目くらいに string_t CNPC_Citizen::GetModelName() const という関数がある。 こやつを

string_t CNPC_Citizen::GetModelName() const
{
/*
    string_t iszModelName = BaseClass::GetModelName();

    //
    // If the model refers to an obsolete model, pretend it was blank
    // so that we pick the new default model.
    //
    if (!Q_strnicmp(STRING(iszModelName), "models/c17_", 11) ||
        !Q_strnicmp(STRING(iszModelName), "models/male", 11) ||
        !Q_strnicmp(STRING(iszModelName), "models/female", 13) ||
        !Q_strnicmp(STRING(iszModelName), "models/citizen", 14))
    {
        return NULL_STRING;
    }

    return iszModelName;
    */
    //return NULL_STRING;
    return MAKE_STRING("models/sdk/Humans/jajiman05.mdl");
}

と変更する。 くどいようだが、jajiman05.mdlというのはstudiomdlでコンパイルした自分のモデルである。 hammer editorでは、 npc_citizenのModelを自由に選べるようにはなってないので、 ソースでむりやりすべてのモデルをjajiman05に変更しているというわけ。

ここで非常に悩んだのは、 vc++2008eeはstring_tの定義はconst char であって、 MAKE_STRINGは単なるダミーの定義だと言い張るのだが、 どうもそんなわけじゃないらしい。 なんとなく#ifdef ... #endifでコメントアウトされている部分が生きてる気がする。 つまりコンパイルするときに渡される環境変数がうまく反映されてないんじゃないかとか。 ともかくMAKE_STRINGをかませるとchar をstring_tにキャストできるので良しとする。 c++はcと違ってキャストが四種類ありうんぬんとか visual studioとかCLIは文字列のキャストがめちゃくちゃ複雑とか、 ネット読んでると絶望しそうになったが関係なかったらしい。

で、npc_citizenを無理矢理jajiman05にすることには成功したのだが、 sequence (ジェスチャーとかポーズとか要するにモデルのアニメーションのたぐい) がなくてjajiman05がただidleのポースで立ち尽くすだけである。 たとえばd1_trainstation_01で一番最初に出てくるnpc_citizenは Humans/Group01/Male01というモデルで、 電車の中で右手にトランクを持ち左手で手すりにつかまっているのだが、 このsequenceの名前はd1_t01_TrainRide_Standという。 このMale01をモデルビューアでみるとちゃんとそのsequenceが用意してある

そこで、GCFSccapeを使ってsource model.gcfからmodels\Humansにある male_ss.mdlというやつを抽出し、 さらにmdldecompilerでQCファイル(mdldecompiler.qc)とアニメーションのファイルd1_t01_TrainRide_Stand.smd を取り出す。 mdldecompiler.qcを参考に jajiman05.qcにsequenceを追加する:

$sequence d1_t01_TrainRide_Stand "d1_t01_TrainRide_Stand" loop fps 30.00

このような作業を延々繰り返して、 最後に jajiman05.qcをコンパイルしてjajiman05.mdlを作り直す。 そうすると完全ではないがなんとなく動くようになる。 他人の姿勢や動作をもらってきてそのまま使える場合もあり、 なんか膝が地面にめり込んでたり、椅子じゃないところに座ってたり。 いろいろ不都合はあるようだ。

d1_trainstation_01.vmfをコンパイルしただけではmodで完全に動かすことはできないのだろうかねえ。 d1_trainstation_01などはあまりにも複雑なマップなので、 どこがどう問題なのか理解しがたい。 まあ、modを作るとしてもこんな複雑なマップを作るつもりはないので、 とりあえず動いたということで今回はこれでいいかな。

上のフラッシュムービーで、 元のhalf-life2をやったことない人にはいまいちピンと来ないと思うが、 最初に顔アップで出てくるおっさんはG-Manというのだが、 ほんとうならばクチパクで何かGordon Freemanに話しかけるセリフがあるのだが、 それもない。 電車に乗り合わせる二人の男も電車が止まると外に出るのだが出ない。 つついても返事をしない。 お巡りにいたずらしても怒って追いかけて来たりもしない。 などなど。