alchemistarkの日記

やったことのメモ

Entityについて解説したい 2

InputとOutputについて解説すると言ったな?
あれは嘘だ

InputとOutputするにはまずInputOutputしたいEntityを見つける必要がありますね
InputOutputについてはそれから

ここでは例として"team_control_point"エンティティを探してみるよ
これはキャプチャーポイントのEntityで、A/Dや5CPやKOTHに設置してあるアレね。
なお、画面に表示されてるCPのHUDやキャプチャー可能なエリアを設定してるのは別のエンティティだよややこしいNE

team_control_point - Valve Developer Community
Entityの詳細ページはこちら。

Entityを探す関数はFindEntityByClassname関数

FindEntityByClassname · sdktools_functions · SourceMod Scripting API Reference
関数の説明はこちら。

この関数は、指定したEntity番号以降のEntityの名前を順番に検索していって、最初に指定の名称のEntityを見つけたらそのEntity番号を返します。
なので検索して出てきたEntityが、自分の求めているEntityかどうかはまた色々しないと分かりません。

使い方。はいこれテストに出まーす。

new ent = -1;
while((ent = FindEntityByClassname(ent, "team_control_point")) != -1){	//名前からエンティティを探す
	PrintToServer("Entity %d はteam_control_pointです",ent);
}

まず、初期値が-1なので、存在する一番若番のEntityから検索を開始します。
Entityのクラス名が"team_control_point"のEntityを発見したら、そのEntity番号を返してくるので、entの値が更新されます。
見つかったEntity番号に対して処理を行った後、そのEntity番号を引数に再度検索します。
Entityが見つからなかったら-1が返されるので、ループを抜けます。

つまり、Entity番号が0から9の10個のEntityがあったとして、そのうち2と5がteam_control_pointだったとすると、

Entity 2 はteam_control_pointです
Entity 5 はteam_control_pointです

となるわけ。
例えば、kothとかだとCPは1つですが、5CPだと5つあるので上記の例だとPrintToServerが5回実行されるはず。

何故ループを回す必要があるかは単純に同じ種類のEntityが複数あった場合、探しているEntityが検索した1件目とは限らないため。
Entity番号がどう振られているかは決まっていないので、上記の場合探しているteam_control_pointが2か5かは分からない。今回2だったからって次も2とは限らないし、4になってるかもしれない

では中央CPだけ取得したい場合はどうすれば良いか、なのですが
GetEntPropでm_iDefaultOwnerが0のCP探せばいいんじゃないかな多分
これの說明はまた後でします。
基本的には総当りして、条件に合致するEntity見つけたら抜ければOK

とにかくこれでteam_control_pointのEntity番号が分かりました。

次こそInputとOutputやるよ 多分

Entityについて解説したい 1

詰まるようなところでは無いのかもしれないが、自分は延々と詰まったので解説したい
だがどこからどう解説したものか…

「自分はこういう認識をしている」という体で話します。
実際どうであるかとはかけ離れている可能性は大いにあります。


Entityとは、ゲーム上に存在するほぼ全ての物がEntityです。地面を転がっている酒瓶から、プレイしているプレイヤーキャラクターもEntityです。
ここではそう認識します。ぶっちゃゲーム内で管理されていていて個別の番号を割り振られているオブジェクトの事をEntityだと思ってて特に困らないと思います。
逆に、Entityで無い物もあります。地面や壁等のsolidがそうです。ただし、Entity化されたSolidを除きます。*1
このあたりはマップ制作の話に被ります。Entityを分かるのに避けて通れないと思うので、プラグイン開発者はHammerの最低限の知識が必須です。*2

Valve ハンマーエディタ講座 4.1
必読ですよ というかHammerの資料少なすぎやしませんか…
こちら必要な事は一通り抑えてあり、記述している所を一通りやれば次に必要な事は自分で見つけられると思います。

尚、TF2のHammerEditerはtf2インストール配下のbinフォルダ内にあります。SourceSDKは不要です
大事なことなのでもう一度言います。SourceSDKは不要です

話が少しそれましたが、Entityは大きく分けて2種類あります。
・SolidをEntity化したbrushエンティティ
・マップ上に直接設置、もしくはゲームエンジンが動的に生成するpointエンティティ
ポイントエンティティは実体を持つ(ゲーム上に表示される)物と、実体を持たない(表示されず、機能のみを持つ)ものがあります。

ブラシエンティティは例えばキャプチャーエリアの範囲やリスポンルームの範囲等を作る事ができます。
ポイントエンティティは弾薬やヘルスキット等のアイテムや、ゲームのタイマー、物理演算オブジェクト等多岐に渡ります。

Entityの一覧を貼っておきます。
どのようなEntityがあってどんな機能を持っているのか、見てみても良いかもしれません。

SourceEngine全般
List of base entities - Valve Developer Community

TF2
List of Team Fortress 2 Entities - Valve Developer Community


次があったらInputとOutputの話をします。
とりあえず今回はゲーム上の殆どのものはEntityなんだって思ってくれたらOKです。

*1:ごく例外として、Solidを生成して消えてしまうEntityもあります…prop_staticとかがそうです

*2:Entityのプロパティに何があるか確認するだけでも凄い助かる

KothIntelプラグイン

KothでCPの代わりにインテルを使うプラグイン
インテルを拾っている間タイマーが動作します。落とすと止まります。


リスポン前に要塞作った園児がインテル持って立てこもるんですよね分かってます

ソースは貼りません(面倒になった)
希望者はご連絡ください

kothのタイマー続き

更に遠回りしてた。
対象のEntityが分かったんならそれのInput叩けばいいんじゃないかな!?

といわけでkothのタイマーを停止、再開、設定するプラグインできたよ
kothマップを改造して何か作ろうとした時に使えると思うよ

以下全文。

続きを読む

kothのタイマーを操作する

クソみたいに遠回りした…
とりあえず順番に語ります。本題だけ見たい人は最後のコードを見てください。


kothのタイマーを操作したい
とりあえず止めたり動かしたり時間を変えたりしたい

ではkothのタイマーはどこにあるのか?
とりあえず思いつくのはtf_logic_koth、tf_gamerules、team_round_timer

tf_logic_kothはとりあえずkothのHUDを表示してる
後タイマーにセットする時間を持っている

tf_gamerulesにはkoth関係と思われるInputはSetRedKothClockActiveとSetBlueKothClockActiveしかない
これはkothのタイマーをスタートさせるだけ 一方が動き出すともう片方は止まる。

team_round_timerは複数のマップをHammerEditerで開いてみたところ、
そもそもkothマップには置いてない事が多いように見える。

つまり、bspファイル内にkothのタイマーを記録しているEntityは存在しない…?

と思っていたらtf_logic_kothのページにこのような記述を発見。

It creates two entities named zz_red_koth_timer and zz_blue_koth_timer which have inputs like pause,resume,etc

これは、zz_red_koth_timerとzz_blue_koth_timerという名前の2つのエンティティを作成します。これらのエンティティには、一時停止、再開などの入力があります。

動的に作ってんのかよ!!!

じゃープラグインからzz_*_koth_timerってEntity探したり作ったりしてみようか
まで考えたけど見つからないし作成できず。

うん、僕バカなのでzz_*_koth_timerってClassnameでEntity探したよね

個別のEntity名ですってば。プロパティ名で言うとtargetname
恐らくEntityClassnameはteam_round_timerだと思われ

HammerEditerでOutput先にzz_~を指定するとOutput先が存在しないって言われるけど動作します。
何かのイベントが起きるとタイマーが止まるkothマップとか作れます。

zz_~で調べてたら、その名前で引っ掛けてEntityを特定してるコードを発見。
けどもう少し調べたらtf_gamerulesのNetPropに普通に格納されてた
んでtf_gamerulesはsdktoolsをincludeしたらGameRules_GetPropEntで読めるから…
あれ、これコード凄い単純じゃね…?

以下コード。

public Action:Cmd_get(client, args){

	//タイマーのEntityを確保する
	new bluetimerEnt = GameRules_GetPropEnt("m_hBlueKothTimer");
	new redtimerEnt = GameRules_GetPropEnt("m_hRedKothTimer");

	new float:fBluTime;
	new float:fRedTime;
	
	//青タイマー確認	//止まっていると1、動いていると0
	if(GetEntProp(bluetimerEnt, Prop_Send, "m_bTimerPaused") == 0){
		//タイマー動作中(タイマー開始時の時刻-現在時刻)
		fBluTime = GetEntPropFloat(bluetimerEnt, Prop_Send, "m_flTimerEndTime") -  GetGameTime();
	}
	else{
		//タイマー停止中
		fBluTime = GetEntPropFloat(bluetimerEnt, Prop_Send, "m_flTimeRemaining");
	}
	
	//赤タイマー確認
	if(GetEntProp(redtimerEnt, Prop_Send, "m_bTimerPaused") == 0){
		fRedTime = GetEntPropFloat(redtimerEnt, Prop_Send, "m_flTimerEndTime") -  GetGameTime();
	}
	else{
		fRedTime = GetEntPropFloat(redtimerEnt, Prop_Send, "m_flTimeRemaining");
	}
	
	//表示する
	PrintToChat(client,"Blue:%f Red:%f",fBluTime,fRedTime);
	PrintToChat(client,"BlueTimer:%d RedTimer:%d",GetEntProp(bluetimerEnt, Prop_Send, "m_bTimerPaused"),GetEntProp(redtimerEnt, Prop_Send, "m_bTimerPaused"));
	
	/*
	SetEntProp(bluetimerEnt, Prop_Send, "m_bTimerPaused",1);
	"m_bTimerPaused"に1を書き込むとタイマーが停止するが、同時に"m_flTimeRemaining"の値でタイマーが上書きされる
	停止させる前に手動で"m_flTimeRemaining"の値を更新すること
	また、CPは取得されたままになるのでCPの所有者を開放する等の処置を取ること
	*/
	
}

多分team_round_timeのInputが使えるので、全部GetEntPropする必要は無いと思う。
コメントにも書いてるけど、タイマーをただ停止させるとタイマーが動く前の時間に戻されるので注意。
先にTimeRemainingの値を書き換えておけばOK

そういえば両方動かしたら両方同時に動き出してちょっと笑える

ていうか最終的にコピペしたのがmorestocksなのちょっと納得行かない
つまりmorestocksをincludeした方が断然早い。

sourcemod-snippets/tf2_morestocks.inc at master · powerlord/sourcemod-snippets · GitHub

SouceModプラグインの開発を始めるにあたって必要なもの

SourcePawnのWiki作ろうって瞬間だけ思って放置してるやつに書いてたやつ。

準備するもの

プラグインのアイディア、プラグインを作成して行いたいこと

これが無ければ始まりません。

MetaMod、SourceModが動作する環境

srcdsのインストールにて解説します。(機会があれば書きます)

SourcePawnのコンパイラ

SourceModがインストールされていれば、
addons/sourcemod/scripting/compile.exe
にあります。

また、ブラウザから利用できるコンパイラとしてSourceModの配布ページの
www.sourcemod.net

こちらか、

Spider - SourcePawn Compiler

こちらが利用できます。

下の方はincファイルのincludeができるのでこちらの方が少々多機能です。

テキストエディタ

文字コード UTF-8(BOMなし)で保存できるエディタ なら何でも良いです。
プラグイン自体は文字コードを問いませんが、KeyValueを使用する時に使うファイルは UTF-8(BOMなし)である必要があります。

お好みのエディタがあるならばそれを、特にこだわらないならNotepad++を推奨します。
「Notepad++」オープンソースで開発されているプログラマー向けのテキストエディタ
forest.watch.impress.co.jp


SourcePawn用のハイライト機能を使うことができます。

こちらで配布されています。
forums.alliedmods.net


プラグインになりますが、NppExecというプラグインを導入することによって保存してそのままコンパイラにファイルを送ることができるので、
こちらも導入を推奨します。

NppExecの使い方を解説しているページ
NppExec (コマンドの実行) | Notepad++のプラグイン解説




設定例

NPP_SAVE 
(インストールフォルダ)\addons\sourcemod\scripting\spcomp.exe "$(FULL_CURRENT_PATH)" 
powershell move $(NAME_PART).smx (インストールフォルダ)\addons\sourcemod\plugins\ -force

別にpowershellで無くても良いですが、サーバーパスがsmbの向こう側だったりすると必要です。

以上が揃えばプラグインを書く準備が整います。

PropSpawnプラグイン

クソプラグイン作った
指定したPropを出現させて位置を設定、設置した位置を保存できる
ラウンド開始時に自動でロードする機能付き
マップをカスタムしたりしてどうぞ

以下ソースコード全文

続きを読む