alchemistarkの日記

やったことのメモ

PLマップの判定

マップロード時に出る画面やmotdでのルール表示でペイロードと表示するには

まぁEntityのページに書いてあるんですけどね。気付くかこんなもん。

team_train_watcher - Valve Developer Community

srcdsのインストール方法補足

srcds、つまりSourceEngineゲームのサーバーを建てる方法について。
今回はWindows版のtf2のサーバーの話します。
他のゲームの鯖建てもゲームID変えるぐらいでほぼ同じはず
tf2鯖でのみ起きる現象について少しだけ補足します。

まずこちらのサイトをご覧ください。

TF2Wiki サーバーの建て方の基本
http://tfortress2.wikiwiki.jp/?WindowsXPtfortress2.wikiwiki.jp

srcdsのインストール方法全部書いてあります。完。
ダメですかそうですか。

でも一通り読んでください。以降読んでるの前提で、書いてない事補足します。

SteamCMDのバッチファイルはコレだけ書いてれば十分です。

steamcmd +login anonymous +force_install_dir ../tf2 +app_update 232250 validate +quit

steamcmd.exeと同階層にbat置いて、1つ上にtf2フォルダ作ってその中にインストールする用になってるのでインストールパスは適時変えてください。

記事作成現在、tf2のsrcdsはGUIモードで起動できないので、コンソールで起動する必要があります。
普通に起動したら真っ黒のウィンドウが出るだけだし、閉じてもプロセスが残ってCPUゴリゴリ食う

f:id:alchemistark:20180313234531p:plain

GUIの方もパラメータ渡さないと起動しないとか色々あるんですが考えなくてOK 漢は黙ってコンソール

僕の鯖の起動バッチ置いておきます。

start /affinity 2 srcds.exe -game tf -secure -port 27015 +rcon_password "****" +map koth_king -console -nocrashdialog

以下説明。

・start /affinity 2

srcdsはマルチコアに対応してないらしいので、使用するCPUコアを直接指定している
別にどのコアでもいい 数値はビットマスク16進
speedup-xp.com

・-game tf
ゲームによっては不要だと思うが、TF2の場合明示的にtfを指定しないと起動しない。たしかL4D2だと要らない

・+map
なんでもいいからマップ指定しておかないと起動しない。ていうか起動はするけど接続できない。

・-console
CUIで起動する cmdから起動しようがPowerShellから起動しようが新たにcmd窓生成してウザい。バックグラウンド化して必要な時だけコンソール見たいんだけど。
SSH経由で起動したらどうなるんだろう誰か試して

・-nocrashdialog
メモリエラーとかでクラッシュした時にダイアログを出さずにプロセスを終了する
ダイアログ出ても復帰するわけでもないので… 後プロセス監視するツールとか入れて再起動させる場合必須
ダイアログ出した場合鯖は死ぬのにプロセスだけ生き残る為

どのConVarを弄ったか分からなくなった時


バニラのcvarlistと現在のcvarlistをdiffソフトで比較してた僕の話する?
ただこの方法、追加されたcvarも発見できるのでこれはこれでオススメ*1

後、aliasもこれだけ入力されると作成したaliasの一覧が出力されるので
追加したaliasが悪さしてるとか、多重に定義した(大文字小文字が区別される)時とかに便利。

aliasの削除方法知らないので、もしご存じの方いらっしゃいましたらご一報ください。

あ、aliasはクライアントだけじゃなくてsrcds側でも設定可能です。
プレイヤーからはもちろん呼び出せませんが。
じゃぁ何が面白いかというと、vote系プラグインとかでtoggle仕込んだりとかそういうことします。
プラグインの有効無効がcvarじゃなくて別cmdだったりするときとか。

*1:公式の更新情報見ろって話は受け付けません

棚作った

 

 

 

 

 

Entityについて解説したい 6

ではEntPropについてお話するよ

InputはEntityに命令するもの、KeyValueはEntityの設定
EntPropはメモリの読み書き*1

一番面倒だけど出来ることも多い

GetEntProp系は読み出し、SetEntProp系は書き込み
EntPropも型ごとに関数がある String、Float、Vector、Ent
EntityIndexを扱う時はDecimalじゃなくてEntを使う
関連関数多すぎるのでAPIページ貼るのは省略してSetEntPropのみで

SetEntProp · entity · SourceMod Scripting API Reference
最後2つの要素は省略可。一番最後のはプロパティが配列の場合のみ使う

そもそもEntityというかEntPropを初めて見かけるのって
恐らく無敵化するにはどうするか調べてるときじゃないかなって思う*2

SetEntProp(client, Prop_Data, "m_takedamage", 1);

最初これ見た時の感想、m_takedamageってなんやねんだったんだけど僕だけかな
ググっても出てこないし、何だこれはってなった SourceModのページにNetProps一覧とか置いてあるんだけどその中にもm_takedamageって無いんですけど!?

答えから言います m_takedamageはdatamapにあります。
とりあえずdatamapとはなんぞやは置いておいて*3
コンソールにfind sm_dumpと入力してください。

f:id:alchemistark:20180212000624p:plain

えっと、分かるものだけ説明します。

sm_dump_datamaps datamap.txt
とかするとdatamapの一覧が保存されます。
開くと大量のプロパティ名だかメモリ名だかが出てきます。

// Dump of all datamaps for "tf" as at 2018/02/11
//
//
// Flag Details:
//
// Global: This field is masked for global entity save/restore
// Save: This field is saved to disk
// Key: This field can be requested and written to by string name at load time
// Input: This field can be written to by string name at run time, and a function called
// Output: This field propogates it's value to all targets whenever it changes
// FunctionTable: This is a table entry for a member function pointer
// Ptr: This field is a pointer, not an embedded object
// Override: The field is an override for one in a base class (only used by prediction system for now)
//

CBaseEntity - _ballplayertoucher
- m_iClassname (Offset 92) (Save|Key)(4 Bytes) - classname
- m_iGlobalname (Offset 96) (Global|Save|Key)(4 Bytes) - globalname
- m_iParent (Offset 100) (Save|Key)(4 Bytes) - parentname
- m_iHammerID (Offset 104) (Save|Key)(4 Bytes) - hammerid
- m_flSpeed (Offset 108) (Save|Key)(4 Bytes) - speed
- m_nRenderFX (Offset 112) (Save|Key)(1 Bytes) - renderfx
- m_nRenderMode (Offset 113) (Save|Key)(1 Bytes) - rendermode
- m_flPrevAnimTime (Offset 136) (Save)(4 Bytes)
- m_flAnimTime (Offset 140) (Save)(4 Bytes)
- m_flSimulationTime (Offset 144) (Save)(4 Bytes)
- m_nLastThinkTick (Offset 152) (Save)(4 Bytes)
- m_nNextThinkTick (Offset 208) (Save|Key)(4 Bytes) - nextthink
- m_fEffects (Offset 212) (Save|Key)(4 Bytes) - effects
- m_clrRender (Offset 132) (Save|Key)(4 Bytes) - rendercolor
- m_nModelIndex (Offset 114) (Global|Save|Key)(2 Bytes) - modelindex

……

右側にclassnameだとかhammeridだか書いてあるものは、プロパティ名に関連付けられています。
なのでそこを変更すると対応するプロパティの値も変わります。

1行目のCBaseEntity - _ballplayertoucherってのはEntityのClass名
この種類のEntityはこのプロパティ(メモリ?)を持ってますよって感じ
例えばteam_round_timerで検索してみると

CTeamRoundTimer - team_round_timer

ってのが引っかかるので、これより下がteam_round_timerにEntPropする時に使えるもの一覧になります
型はm_の次の1文字2文字で型の頭文字付いてるのでそれで 絶対じゃないけど

んでdatamapに対してGetやSetをする場合、Prop_Dataを指定します。

SetEntProp(client, Prop_Data, "m_takedamage", 1);

再掲。


次。netprop。
ネットワーク化可能なうんたらって多分コレの事だとは思うんだけど…

ぶっちゃけコレも同じ。
一度ファイルに保存します。
中身はこんな感じ

CBaseDoor (type DT_BaseDoor)
 Table: baseclass (offset 0) (type DT_BaseEntity)
  Table: AnimTimeMustBeFirst (offset 0) (type DT_AnimTimeMustBeFirst)
   Member: m_flAnimTime (offset 140) (type integer) (bits 8) (Unsigned|ChangesOften)
  Member: m_flSimulationTime (offset 144) (type integer) (bits 8) (Unsigned|ChangesOften)
  Member: m_vecOrigin (offset 792) (type vector) (bits 0) (ChangesOften|CoordMP)
  Member: m_ubInterpolationFrame (offset 148) (type integer) (bits 2) (Unsigned)
  Member: m_nModelIndex (offset 114) (type integer) (bits 13) ()
  Table: m_Collision (offset 348) (type DT_CollisionProperty)
   Member: m_vecMinsPreScaled (offset 8) (type vector) (bits 0) (NoScale)
   Member: m_vecMaxsPreScaled (offset 20) (type vector) (bits 0) (NoScale)

使い方も似たようなもん。ただ、Prop_DataがProp_Sendになります。

ちょっと待ってCBaseDoor (type DT_BaseDoor)って何って思った人が出てくると思う
それを調べるにはclasslistを見る必要があるので
sm_dump_classesしてください。
中身はこちら。

// Dump of all classes for "tf" as at 2017/12/06
//

CBaseEntity - _ballplayertoucher
CFireSmoke - _firesmoke
CPlasma - _plasma
CBaseEntity - ai_ally_speech_manager
CBaseEntity - ai_battle_line
CBaseEntity - ai_changehintgroup

…中略…

CBaseEntity - func_croc
CBaseDoor - func_door
CBaseDoor - func_door_rotating
CFunc_Dust - func_dustcloud

CBaseDoorありました。func_doorとfunc_door_rotaingですね。
尚、さらに下の方に行くとfunc_waterもCBaseDoorなのが分かります。
このように似たようなEntityは同じプロパティを持っていたりします。
NetProp使う時は一旦classlistからEntity名検索して該当のクラスを探してください。

tempentity propsってなんですかぼくはしりません

とりあえずここまで説明したInput、KeyValue、EntPropでEntityの操作は大体できると思います。
InputやKeyValueで操作できる内容ならなるべくそちらの方がいいかもしれません。
InputやKeyValueにもよるのですが、1つのInputやKeyValueの操作で、複数のPropが変更されている事があるようです。
その場合、変更が必要なPropが全て分かっているのなら良いのですが、そうでなくPropの設定変更が不足していた場合想定外の動作をする可能性があります。
デバッグ繰り返して問題なければ大丈夫だと思いますが…

6回に渡って長文書きましたが、日本語怪しすぎて読めないとは思いますが
入門者の助けになれば幸いです。
良いプラグイン開発を

*1:だと僕は思ってる

*2:偏見

*3:自分も分かってない

Entityについて解説したい 5

いい加減雑になってきたEntity講座にようこそ

1度書いた下書きが消えた 悲しい


今回はKeyValueについてちょっと話します

Entityのページとかで最初の方にあるKeyValueの一覧
あれは何かって話なんですが、HammerでEntityのプロパティ開いたら出るやつです。

f:id:alchemistark:20180209172101p:plain
ついでにヘルプも開いておいた

設置したEntityの名称やらオプションやら設定するとこですね
SmartEditを外した時に出てくるのが正式なプロパティ名なのでSourcePawnからはそちらを使います。
ただ、この画面では全てのプロパティは表示されていないので、一部のプロパティをSmartEditを使わずにHammerから設定するにはKeyとValueをAddする必要があります。
まぁHammerからやる場合はSmartEditでやるだろうから関係ないかな…

SourcePawnからKeyValueを設定する関数はDispatchKeyValue、DispatchKeyValueFloat、DispatchKeyValueVector
それぞれString、Float、Vectorに対応。

DispatchKeyValue · sdktools_functions · SourceMod Scripting API Reference
DispatchKeyValueFloat · sdktools_functions · SourceMod Scripting API Reference
DispatchKeyValueVector · sdktools_functions · SourceMod Scripting API Reference

プロパティの型はEntityのページやヘルプを参照。実際にHammerで値を設定してみて何が入るか確認するのもいいと思う。

new ent = CreateEntityByName("prop_physics_override");
DispatchKeyValue(ent, "targetname", "prop_1");
DispatchSpawn(ent);

使い方と言うほどのものでもないけど、こんな感じでプロパティを設定できる。
作ったEntityに名前付けておけばFindEntityByClassnameで検索した時に特定が容易
CreateEntityByNameはそのまんまEntityを作成する DispatchSpawnしないとゲーム内に出現しないので注意
プロパティの設定はスポーン前でも後でもできるけど、スポーン前だと反映されないプロパティとかあるので
スポーン後にまとめてでもいいかもしれない。

CreateEntityByName · sdktools_functions · SourceMod Scripting API Reference
DispatchSpawn · sdktools_functions · SourceMod Scripting API Reference


次はEntPropの話するよ ようやく本題感ある

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から設定できるなら教えてほしい