ponpoko実験室

1.新しいクライアント用コマンドを追加してみる

 Quakeのコンソールコマンドで"cmd help"は使用するアイテムを選択するコマンドで、デフォルトの設定ではF1キーへバインドされています。 ゲームを開始していない状態で(例えばデモが流れている最中)このコマンドを実行するとCan't "cmd" not connected(「ゲームのポートへ接続してないので"cmd"は実行できない」という返事が戻ってくるところからゲームクライアント用のコマンドだということが伺えます。
 そこでクライアントコマンド"cmd"について調べてみたところその処理を行っている部分が見つかりました。

 "cmd"へ与えられたパラメータを取得するにはインポート関数argvを利用します。
 例えばQuake2のコンソールから(ゲーム中に)

cmd pokemon koremon bakamon

と実行された場合argv(int n)の戻り値は以下のようになります。

引数 n戻り値のポインタにある文字列
0pokemon
1koremon
2bakamon
これを利用して実験を行ってみました。Quake2ソースのg_cmds.cから関数ClientCommandを定義している部分を探し出して(一番後ろにあります)以下にで示した部分を追加してみてください。

/*
=================
ClientCommand
=================
*/
void ClientCommand (edict_t *ent)
{
	char	*cmd;

	if (!ent->client)
		return;		// not fully in game yet

	cmd = gi.argv(0);
	if (Q_stricmp (cmd, "use") == 0)
		Cmd_Use_f (ent);
	else if (Q_stricmp (cmd, "drop") == 0)
		Cmd_Drop_f (ent);
	else if (Q_stricmp (cmd, "give") == 0)
		Cmd_Give_f (ent);
	else if (Q_stricmp (cmd, "god") == 0)
		Cmd_God_f (ent);
	else if (Q_stricmp (cmd, "notarget") == 0)
		Cmd_Notarget_f (ent);
	else if (Q_stricmp (cmd, "noclip") == 0)
		Cmd_Noclip_f (ent);
	else if (Q_stricmp (cmd, "help") == 0)
		Cmd_Help_f (ent);
	else if (Q_stricmp (cmd, "inven") == 0)
		Cmd_Inven_f (ent);
	else if (Q_stricmp (cmd, "invnext") == 0)
		SelectNextItem (ent);
	else if (Q_stricmp (cmd, "invprev") == 0)
		SelectPrevItem (ent);
	else if (Q_stricmp (cmd, "invuse") == 0)
		Cmd_InvUse_f (ent);
	else if (Q_stricmp (cmd, "invdrop") == 0)
		Cmd_InvDrop_f (ent);
	else if (Q_stricmp (cmd, "weapprev") == 0)
		Cmd_WeapPrev_f (ent);
	else if (Q_stricmp (cmd, "weapnext") == 0)
		Cmd_WeapNext_f (ent);
	else if (Q_stricmp (cmd, "kill") == 0)
		Cmd_Kill_f (ent);
	else if (Q_stricmp (cmd, "putaway") == 0)
		Cmd_PutAway_f (ent);
	else if (Q_stricmp (cmd, "wave") == 0)
		Cmd_Wave_f (ent);
	else if (Q_stricmp (cmd, "gameversion") == 0)
	{
		gi.cprintf (ent, PRINT_HIGH, "%s : %s\n", GAMEVERSION, __DATE__);
	}
	else if (Q_stricmp (cmd, "fov") == 0)
	{
		ent->client->ps.fov = atoi(gi.argv(1));
		if (ent->client->ps.fov < 1)
			ent->client->ps.fov = 90;
		else if (ent->client->ps.fov > 160)
			ent->client->ps.fov = 160;
	}
	else if (Q_stricmp (cmd, "bakamono") == 0)
	{
		if (Q_stricmp (gi.argv(1), "death") == 0)
		{
			gi.cprintf (ent, PRINT_HIGH, "Bokucyan Death!\n");
		}
		else	gi.cprintf (ent, PRINT_HIGH, "Bokucyama Decyu!\n");
	}
	else
		gi.cprintf (ent, PRINT_HIGH, "Bad command: %s\n", cmd);
}

 上記リスト中に見られるQ_stricmpは普通のstrcmp関数と同じく2つの文字列を比較するもので、両方同じ文字列なら戻り値は0になると覚えておけばいいと思います。
 さて、この変更後に作ったgamex86.dllでQuakeを起動してシングルかマルチプレイでゲームをスタートさせたら。コンソールから

cmd bakamono

と入力してください。すると"Bokucyama Decyu!"と答えが返ってくるはずです。次に

cmd bakamono death

と入力すれば答えは"Bokucyan Death!"。はい、簡単ですね。この調子で勝手に自分のコマンドを作って好きな処理へ飛ばすなりなんなりすればよいのです。


e-mail:ponpoko@axcx.com