ponpoko実験室
3.Quake2のimpulse値を取得するには?
Quakeのカスタムモジュール界では超ポピュラーだったユーザー用のコマンドimpulse、Quake2でも生きておりました。
この言葉を初めて耳にする方のために説明しますとコンソールコマンド"impulse"は
impulse n
の形でパラメータnへ任意の値(0〜255)を指定して実行するとimpulse値(impulseコマンド実行時以外は常に0)が1フレームの間だけnへ変化し、次のフレームでは0へ戻るというコマンドです。
なお、ノーマル状態のQuake2ではimpulseコマンドは生ける屍状態で、何の用途にも使われていません。
しかし、impulseへ親しんできたQuakerとしては何としても使ってみたいコマンドなので、今回はimpulse値を取得する方法について説明します。
ソースp_client.c中にはプレイヤーのために毎フレームごと(ゲームの状態によってはサーバーの1フレーム中に複数回呼び出されることになることも有りうる)に呼び出されるClientThink関数があります。
この関数はサーバーから与えられる情報を元にプレイヤーの挙動を制御(移動その他)する関数で、呼び出される際に与えられる引数のusercmd_t型構造体メンバにimpulse値は含まれています。
参考のために、usercmd_t型構造体はどのように定義されているのか以下に示します。
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
short forwardmove, sidemove, upmove;
byte impulse; // remove? この値
byte lightlevel; // light level the player is standing on
} usercmd_t;
酷い扱いですね"remove?"とか言われています。
それでは実際にどう使うのか使用例を簡単に示して終わりにしたいと思います。impulse値が0以外の場合、その値を表示させるようにしてみましょう。ソースp_client.c中から以下リストのClientThink関数定義位置を探し出し、赤で示した部分を追加してみてください。
/*
==============
ClientThink
This will be called once for each client frame, which will
usually be a couple times for each server frame.
==============
*/
void ClientThink (edict_t *ent, usercmd_t *ucmd)
{
gclient_t *client;
edict_t *other;
int i, j;
pmove_t pm;
if( ucmd->impulse != 0 )
gi.cprintf (ent, PRINT_HIGH, "value \"impulse\" = %3i\n", ucmd->impulse );
level.current_entity = ent;
client = ent->client;
if (level.intermissiontime)
{
・
・
・
・
変更して作成されたgamex86.dllでQuake2を起動したらマルチプレイヤーでゲームをスタートさせ、コンソールから
impulse 120
と打ち込んで実行してみましょう。以下のようにちゃんと表示されましたか?
value "impulse" = 120
何故マルチプレイヤーモードで実験したかというと、シングルプレイモードでコンソールを開くとプレイヤーの情報は更新されない(ClientThink関数が呼び出されない)のに仮想サーバーのフレーム更新は行われ続けるという状態なるからです。
適当なキーへimpulseコマンドをバインドするか、コンソールからimpulseコマンドを入力してリターンを押すとほぼ同時にコンソールを閉じればプログラムから返答がちゃんと戻ってきます。
あとはこのインパルス値を使ってBOTクン発生やフック選択をやればいいと思います。たぶん問題ないとは思うんですが?
e-mail:ponpoko@axcx.com