alchemistarkの日記

やったことのメモ

Entityについて解説したい 4

Outputについて話しましょうか

話すとは言ったけどぶっちゃけOutputについて話すことあまりない

Entityがゲームの進行や与えられたイベントをトリガーにして別のEntityのInputを叩くのがOutputなわけですが
Outputを設定できるのはHammerからMAPを作成する時だけです。*1
そのあたりの詳細はHammer講座を見てください。

では、SourcePawnからOutput関連でできる事はなにか
端的に言うと、
・EntityがOutputを発信したのを検知する
・Outputを発信させる
の2つです。

OutputのHookは、HookEntityOutputとHookSingleEntityOutputの2つ
使い方は大体EventのHookと同じ…でもないけどそんな感じ
指定したクラスのEntityが、指定した名称のOutputを発信したら検知する的な。

各関数については例によってAPIページ見てね
HookEntityOutput · sdktools_entoutput · SourceMod Scripting API Reference
HookSingleEntityOutput · sdktools_entoutput · SourceMod Scripting API Reference

HookEntityOutputだと指定の名称のEntity全てHookしてしまうので、EntityIndexや名称など対象を識別できる情報を控えておくこと
HookSingleEntityOutputだと指定したEntityだけをHookできるけど、うまくいかない事例があったのでケースによっては諦めることになるかも。

あとOutputというよりEntityに対するEventをHookしたいならSDKHooks
SDKHook · sdkhooks · SourceMod Scripting API Reference
これはちょっと違う話になるけど、プラグイン作る時に求めるのはこっちな気はする
ただしこっちは個別のEntityにしかHookできないので、そのあたりは面倒っちゃ面倒

OutputのFireについては前書いた記事を参照のこと
alchemistark.hatenablog.jp

開発版でしか使えないことだけに注意。

後、基本的にOutputはマップに仕込まれたものである以上
マップの中身を把握していないと使えないし
分かるのならば直接Inputを叩いた方がいい

1つのOutputで複数のInputを叩いているとか、絶対に起こり得るイベント(セットアップタイムの終了時とかラウンド終了時とか)
によって引き起こされるイベントを起こすとか、そういう時にしか使えなさそう

Outputを発生させる要因自体は発生しないので勘違いしないように
例えばOnSetupFinishedをFireしてもセットアップタイムはそのまま継続する

*1:SourcePawnから設定できるなら教えてほしい

メモ

接点式のロータリーエンコーダ使うならチャタリング除去が必要そう

www.marutsu.co.jp

回路完全に忘れたからアレだけどたしか基本的に負論理だった気がするからこのままでいいはず



フリップフロップの出力をまとめるにはORでいい
出力反転を使うならORじゃダメって話だったと思う(前の記事で負論理をORでまとめるなって話)
そもそも出力をまとめた後にNOTかければいいのではないだろうか、7414の回路余ってるし。
ただし配線は死ぬ

f:id:alchemistark:20180204231131p:plain

もう回路読めなくなってるのでこれでいいのかすら分からない
一旦ブレッドボードで作るべきだなこれ

Entityについて解説したい 3

InputとOutputについて解説すると言ったな

します


まずEntityのInputとOutputとは何か、なのですが
単純にEntityに何かを入力する、Entityが何かを出力するという認識でOKです。

僕はオブジェクト指向プログラミングというのがよく分かっていない人間なのでこういう說明をするのもなんなのですが
EntityClassnameはそのままクラス、Entityの実体はインスタンス、InputとOutputはメソッドと返り値みたいな感じです。
また別に解説するとは思いますが、インスタンスのようにポンポンEntityを作成する事も可能です。

ブン投げるようでアレですが、InputとOutputに関してはHammerを起動した方が早く分かります。
Hammer講座でドアを作っている部分の解説がそれに当たります。

Valve ハンマーエディタ講座 4.1

Hammerだと、設置したEntityがプレイヤーの動きやゲームの進行によってOutputを発信するように設定し、
そのOutputを別のEntityのInputに送り込むようになっています。*1

SourcePawnからInputを行う場合とは流れが少し違うのですが、まずEntityのInputとOutputがどう設定されているかを上記ページでおおまかに理解しておいてください。

では、SourcePawnからInputとOutputを操作するにはどうするか

とりあえずはInputから。
例としてやはり"team_control_point"を使いますよ
Entityのページを復習しておいてね
team_control_point - Valve Developer Community

new ent = -1;
while((ent = FindEntityByClassname(ent, "team_control_point")) != -1){	//名前からエンティティを探す
	AcceptEntityInput(ent, "Disable");
}

関数のリファレンスはこちら
AcceptEntityInput · sdktools_entinput · SourceMod Scripting API Reference

これでDisableというInputを叩いたので、CPが無効化されます。個別のチェックしてないから見つかったCP全部無効になるね

activator、caller、outputidは省略可能です。
ただし必要とするInputもあるので、上手く動かなかったら指定してやってください。outputidが必要なのは今のところ見たことがないです。
具体的には本来Outputを送るはずだったEntityや、起動したプレイヤーを入れてやると良いです。特になければ0でも。

使えるInputはEntityによって違うので、Entityのページは良く見るようにしましょう。
HammerからもInput名は見えますが、說明は無いので…

なお、KeyValueのところは違います。
HammerでEntityのプロパティを開いた時、最初に表示されているプロパティ一覧がKeyValueです。
Flagは隣のタブだよ

次は、引数を必要とするInputの場合。
例えばSetOwnerというInputは、チーム番号を受け取ってCPをそのチームに取得させます。

	SetVariantInt(TFTeam_Blue);
	AcceptEntityInput(ent, "SetOwner", client, client);

TFTeam_Blueは定数です 3が入ってます。 TFTeam_Redは2 要tf2.inc
今更だけどこの記事で説明してる関数はほぼ全部sdktools.incが必要です*2

SetVariantInt関数の説明はこちら。
SetVariantInt · sdktools_entinput · SourceMod Scripting API Reference

Sets an integer value in the global variant object.

グローバルバリアントオブジェクトに整数値を設定します。

なんだよグローバルバリアントオブジェクトって。

…またよく分かってなくて申し訳ないのですが
僕は専用のバッファかなんかあるんかなぁという認識です。

SetVariant~関数でバッファに値を入れて、AcceptEntityInputでInputを送信する時にバッファの値も一緒に送信しているんだと思います
確かAcceptEntityInputした時に中身消えたと思うから次同じ値使う場合も再度SevVariant~した方がいい…はず した方が無難

SetVariantうんたらという関数が幾つかあるのですが、
これらはInputの引数の型に対応していて
与える値の型に対応した関数を使う必要があります。

んで

	AcceptEntityInput(ent, "SetOwner", client, client);

ここでactivatorとcallerにclient番号入れてますが、SetOwnerはactivator渡さないと動きません…
ポイント取得者を表示するために必要な情報なのだと思います。*3

とりあえずこれでInputは送信できるはず
次はどうしようかな OutputにするかKeyValuleにするかSpawnにするか
EntPropは最後にしようと思ってる*4

*1:HammerだとInput側(受ける側)にもどのEntityからOutputが送られているか表示されるので便利 Input(受ける)側では設定できないのに注意

*2:これは酷い

*3:0でも動くかなどうかな

*4:これが一番有益じゃねーの何で最後やねん

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マップを改造して何か作ろうとした時に使えると思うよ

以下全文。

続きを読む