QuakeC入門

1.Quake-Cの環境を整える

 Quake-CはQuakeのゲーム内容をプログラミングするためのC言語です。 これらのソースを新規作成、もしくは変更し、コンパイルすることによってQuakeのゲーム内容が劇的に変化します。
 例えば、プレイヤーの既存武器改造や新種武器作成、モンスター達の攻撃パターンなどなど。 通常のQuakeで遊ぶことに飽きたら自分で好き勝手に手を加えてしまえばよいのです。 なお、Quake-Cはシェアウェア版での使用ができないため、レジスト版(市販品)が必要となりますので...買えったら買え!

 さっそくQuake-Cのソース、コンパイラ、マニュアルを入手します。Complete Quake-C ver 1.06 package はQuake1.06のQuake-Cオリジナルソースに加え、リファレンスマニュアル、コンパイラ等、必要な物が全て入っています。 Quake Documentation V 3.4の方はQuake-Cオリジナルソースの内容がHTML形式で記述してあり、 ソース上の各所をクリックすることによって関数やオブジェクト、変数の説明を得ることができるので持っているととても便利です。


Quake-C 関連アーカイヴ一式ダウンロード
Title File Name Size Site
Complete Quake-C ver 1.06 package qc106pac.zip 284KB ftp://cdrom.com/pub/quake/utils/quakec/
Quake Documentation V 3.4 qcspec34.zip 264KB ftp://cdrom.com/pub/quake/docs/editing/



 入手できましたでしょうか?qcspec34.zipの方は各自好きなディレクトリへ解凍するとして、 問題はqc106pac.zipです。とりあえずc:\qcc等の適当なディレクトリへ解凍し、 この\qccへ解凍した分は単なるバックアップとしていじらずにとっておくことにしましょう。あとは以下の手順に従ってください。

1.quakeを仮にここではc:\quakeというディレクトリにインストールしてあるとして、 \quakeの下に\testというディレクトリを作って下さい。

2.c:\quake\id1にあるconfig.cfgを1で作った\testにコピーします。これはただ単に今まで遊んできた物と同じOPTION設定 (キー配置や画面の明るさ等)で自分の作成したゲームを起動したいという理由からです。

3.\testの下へ更に\srcというディレクトリを作成し、c:\qcc\v106qc下にあるファイルを全てc:\quake\test\srcにコピー。

4.c:\qcc下にあるqccwin32.exeをc:\quake\test\srcにコピー(パスを通してもたぶん大丈夫、私はメンド臭いので直接コピーして使っています)。


 c:\qccの下にはQcman10.txtがあり、これがQuake-Cのリファレンスマニュアルです。他にもファイルが多数存在しますが、 それらはQuake-Cコンパイラ本体のソースファイルや、qccwin32以外のコンパイラの実行ファイルなので無視しちゃってください。
 c:\qcc\v106qcに格納されているファイルはメモ帳等で見ると改行コードが黒スペース区切りの変な表示になってしまい、見られたものではありません。 この問題は一旦Wordで読み込み、上書き保存を実行すれば解決できます。まず最初に全部のファイルに対して実行して保管しておいた方が良いですね。

 それでは実際にQuake-Cのソースをコンパイルできるかどうか試してみましょう。MS-DOSプロンプトでc:\quake\test\srcへカレントディレクトリを移動してqccwin32.exeを実行します。 qcコンパイラはprogs.srcファイルに指定されたQuake-Cのソースファイルリストを参照してコンパイルしていきます。将来、新規にソースを作成した時はprogs.srcへ新規ソースのファイルネームのソースを追加すればよいのです。 エラーの発生無しに終了しましたか?無事に終了したらc:\quake\test下にprogs.datというファイルができあがっているはずです。次にもう一つ上の階層へ移動し、Quakeを以下のように起動してみましょう。

quake -game test

こうしてやると-gameで指定されたディレクトリの内容を優先的に使用し、 もしも必要なファイルが指定ディレクトリ内に存在しない場合は替わりに\id1のディレクトリ下を参照するように起動してくれるのです(たぶん)。
 Quakeはちゃんと動いてますよね?何!?いつも遊んでるのと変わらない?それは当たり前です、オリジナルソースをコンパイルしただけなんですから。

 これから少しずつソースのあちらこちらを変更して、本当にゲーム内容に変化が現れるか実験します。とりあえずは、えーと、犬の体力モリモリ増加改造です。 dog.qcをメモ帳等で開き、終わり近くにある以下の赤く示した個所を指示どおりに書き換えてください。リスト中の"//"以降の文は注釈なので入力の必要はありません。


		.
		.
		.
void() monster_dog =		//これは犬のentityオブジェクト生成時に呼び出される関数
{
	if (deathmatch)			//ゲームがデスマッチならば犬を削除
	{
		remove(self);
		return;
	}
	precache_model ("progs/h_dog.mdl");		//キャッシュ内へ必要なmodelを読み込み
	precache_model ("progs/dog.mdl");

	precache_sound ("dog/dattack1.wav");	//キャッシュ内へ必要なsoundを読み込み
	precache_sound ("dog/ddeath.wav");
	precache_sound ("dog/dpain1.wav");
	precache_sound ("dog/dsight.wav");
	precache_sound ("dog/idle.wav");

	self.solid = SOLID_SLIDEBOX;		//monster等のSOLIDタイプは殆どSLIDEBOX
	self.movetype = MOVETYPE_STEP;	//犬は地上を歩くのでMOVEタイプはSTEP

	setmodel (self, "progs/dog.mdl");	//使用するmodelを指定

	setsize (self, '-32 -32 -24', '32 32 40');	//犬のサイズを決める
	self.health = 25;			//ここの25を255へ書き換える(体力値)

	self.th_stand = dog_stand1;	//突っ立っている時に呼び出す関数名
	self.th_walk = dog_walk1;	//歩行時に呼び出す関数名
	self.th_run = dog_run1;		//走行時に呼び出す関数名
	self.th_pain = dog_pain;	//攻撃を食らった時に呼び出す関数名
	self.th_die = dog_die;		//死んだ時に呼び出す関数名
	self.th_melee = dog_atta1;	//攻撃時に呼び出す関数名
	self.th_missile = dog_leap1;	//ミサイル接近時に呼び出す関数名

	walkmonster_start();		//犬の活動開始
};


書き換えが終わったらさっきと同じようにコンパイル、Quakeの起動を行い、ちゃんと犬が撃って撃ってもなかなか死なないようになっているかどうか確かめます。

 次の小改造!世の中ズルいやつはいるもので、Quake界で一番の卑怯者はシャンブラーである!weapon.qc(プレイヤーの武器に関するソース)から下に示す赤い行を探し、その部分をさっきと同じ要領で書き換えてコンパイル、Quakeの起動を行います。


		.
		.
		.
void() T_MissileTouch =		//プレイヤーのロケットが物体に接触した際に呼び出される関数
{
	local float	damg;		//ダメージ値計算のためにローカル変数damgを宣言

	if (other == self.owner)	//もしも接触した物体がロケットを発射した本人だった場合は無視
		return;

	if (pointcontents(self.origin) == CONTENT_SKY)	//ロケットが空へめりこんだらロケットを削除
	{
		remove(self);
		return;
	}

	damg = 100 + random()*20;	//random()は0.0〜1.0間の乱数を返す、ロケットのダメージは100に
					//乱数と20の積を加えたものである
	if (other.health)		//接触した相手に体力があった場合
	{
		if (other.classname == "monster_shambler")	//接触した相手がシャンブラーだった場合
			damg = damg * 0.5;	//ここの0.5を10へ書き換える(ダメージ増)
		T_Damage (other, self, self.owner, damg );	//接触した相手にダメージを与える
	}

	// entity other(接触した相手)に対し、爆風による特定空間内ダメージ処理を行わない
	// 既にロケットが接触した際、ダメージを与えているからである
	T_RadiusDamage (self, self.owner, 120, other);	//特定空間内ダメージ処理(無視する相手にotherを指定)

//	sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
	self.origin = self.origin - 8*normalize(self.velocity);		//爆発の表示位置を接触地点より8だけ後退

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);	//テンポラリentityのネットワークメッセージ送信
	WriteByte (MSG_BROADCAST, TE_EXPLOSION);	//ここで爆発音を指定している
	WriteCoord (MSG_BROADCAST, self.origin_x);	//爆発音発生地点を指定
	WriteCoord (MSG_BROADCAST, self.origin_y);
	WriteCoord (MSG_BROADCAST, self.origin_z);

	BecomeExplosion ();		//ロケットは爆発へ変身
};
		.
		.
		.


Quakeのシングルプレイ時、シャンブラーへロケットをいくら撃ち込んでもなかなか死ななくて超ムカッ腹が煮えくりかえったという経験がないでしょうか? 実はシャンブラーのロケットランチャーによるダメージは上記ソースに赤く示された部分で半減されていたのです!キー!くやしーい!
 シングルプレイを開始してコンソールからchangelevel endと打ち込めばいきなり最終面!ロケランでシャンブラーへ20倍返し!一撃で肉片!やーい、ザマミロ!

 さあ、これでもうソースの書き換えやコンパイルはできるようになりましたー! ソースの意味が今一つ理解できないという人、心配いりません。使ってりゃそのうちなんとなく分かります(ほんとかー?)。



e-mail:ponpoko@axcx.com