この文書は SpotMessanger (Mod) 開発の覚書きである。 SpotMessanger のオリジナルは 0.9.10 対応版で開発が終了しており、 本バージョンはオリジナルからの派生バージョンである。
開発バージョン
開発バージョンは GitHub のページ https://github.com/chirimenmonster/wotmods から取得できる。master ブランチがリリース用のバージョン、develop ブランチが開発中のバージョンである。
修正点概要
- 2017/03/04, v0.9.0, オブザーバーモード、被撃破後の観戦モード時の6感には反応しないように修正。設定ファイルリロード、ON/OFF切替時に通知センターに表示。その他バグ修正。
- 2017/02/23, v0.8.0, 0.9.17.1対応版。wotmod 版の追加。
- 2016/12/14, v0.7.0, 0.9.17.0対応版。
- 2016/10/15, v0.6.0, 0.9.16対応版。バグ修正。
- 2016/09/22, v0.5.1, 0.9.15.2対応版。
- 2016/08/05, v0.5.0, 0.9.15.1対応版。内部コードの書き換え。
- 2016/06/10, v0.4.0, 0.9.15.0.1対応版。ログ出力レベルのより詳細な制御。
- 2016/05/25, v0.3.0, 0.9.15対応版。一種類の戦闘モードに対して複数の設定を適用可能。自分が最後のときにアクションを起こさない。
- 2016/04/02, v0.2.0, 0.9.14.1対応版。設定ファイルの書式を変更。6感発動時に実行するコマンドの順序を各戦闘モード毎に指定可能。メッセージ送出後のクールダウンタイム導入。
- 2016/03/14, v0.1.0, 0.9.14対応版。CameraNode.pyc の廃止とフォルダ構成の変更。一般的な mod と同様の配置。
WoT のゲームモード
WoT のゲームモード (戦闘モード) を表す ARENA_GUI_TYPE の識別子は WoT インストールフォルダの res\scripts\common\constants.pyc で確認することができる。 ただし、constants.pyc はバイトコンパイルされた Python のファイル (拡張子が .pyc) なので 内容を知るには後述するように外部ツールを使って逆コンパイルする必要がある。 逆コンパイルしたソースは XVM のリポジトリ https://bitbucket.org/XVM/wargaming.wot.scripts/src でも確認することができる。
WoT クライアントのバージョン 0.9.10 から 0.9.12 の変更で (0.9.11 は欠番)、 ARENA_GUI_TYPE から HISTORICAL が削除された。 そのため、0.9.12 以降で HISTORICAL を判定しようとした場合には値が未定義のエラーとなる。
ARENA_GUI_TYPE, ARENA_GUI_TYPE_LABEL の一覧を以下の表に示す。 0.9.14 では FALLOUT_CLASSIC, FALLOUT_MULTITEAM が追加された。
ARENA_GUI_TYPE | ARENA_GUI_TYPE_LABEL | 備考 | |
---|---|---|---|
0 | UNKNOWN | 'special' | グローバルマップ |
1 | RANDOM | 'random' | ランダム戦 |
2 | TRAINING | 'training' | トレーニング |
3 | COMPANY | 'team' | 中隊戦 |
4 | TUTORIAL | 'tutorial' | 戦闘訓練 |
5 | CYBERSPORT | 'team7x7' | チームバトル |
6 | FALLOUT | ||
7 | EVENT_BATTLES | 'event' | エイプリルフールイベント |
8 | SORTIE | 'fortifications' | 前衛戦 |
9 | FORT_BATTLE | 'fortifications' | 拠点戦 |
10 | RATED_CYBERSPORT | 'team7x7' | ランク戦 |
11 | RATED_SANDBOX | 'ratedsandbox' | (不明) |
12 | SANDBOX | 'sandbox' | 戦車訓練 |
13 | FALLOUT_CLASSIC | 'fallout_classic' | 乱戦? |
14 | FALLOUT_MULTITEAM | 'fallout_multiteam' | 乱戦? |
SpotMessanger は6感が発動したときに動作するので、 6感が発動しなかったり6感を持つ乗員がいないゲームモード、 たとえば戦闘訓練などでは使用されない。
constants.pyc などの拡張子 .pyc のファイルは Python プログラムがバイトコンパイルされたもので人が直接読むことができないが、 Easy Python Decompiler などの解析用ツールを使ってソースに戻すことができる。
SpotMessanger 処理の概要
Mod の登録
mod の読み込み
オリジナル版では ./res_mods/0.9.XX/scripts/client/CameraNode.pyc (XX は WoT のバージョン) に設置した mod loader によって mod を読み込む方式となっている。 これは mod の古い読み込み形式であり、現在では WoT クライアントが mod として ./res_mods/0.9.XX/scripts/client/gui/mods/mod_YYY.pyc (YYY は mod の識別名) を直接読み込む方式がとられる (mod loader を必要としない)。
本バージョンでも後者の新形式によって mod を組み込む。
mod の初期化
新方式で読み込まれた mod_YYY.pyc の内部に init() が定義されていれば読み込み時に実行される。 この中で mod に必要な初期設定を行う。 また、XVM で使用されているものと同等のデコレータを利用して、mod_spotmessanger.pyc の読み込み時に WoT クライアントの内部関数の一部を置き換える。
6感発動処理へのフック
0.9.15.1 で WoT 内部スクリプトの仕様が変わり、6感発動時の処理のフックも変更となった。
- 6感発動時の処理のフック (0.9.15.0.1 まで): Battle._showSixthSenseIndicator(self, isShow)
- 6感発動時の処理のフック (0.9.15.1 以降): SixthSenseIndicator.as_showS()
なお SixthSenseIndicator は gui.Scaleform.daapi.view.battle.shared.indicators で定義される。
キー入力処理へのフック
キー入力処理へのフックは game.handleKeyEvent(event) である。
SpotMessanger では機能のON/OFF切り替え、設定ファイルの再読み込みに使用している。
戦闘開始時のフック
上記2種のフックとは異なり、戦闘開始時のフックは g_playerEvents.onAvatarReady に関数を追加する形で登録することができる。
6感発動時の処理
6感発動時に設定ファイルで指定した条件、順序で各コマンドが実行される。
- チャットメッセージの送出 (Text)
- ミニマップクリック (Command)
- ラジオコマンド F7 (Command)
各コマンドは遅延実行するようにセットされ、重複する場合はスキップされる。 遅延実行は各 Command 間、各 Text 間に所定のインターバルが入るよう計算される。 デフォルトでは Command 間のインターバルは 0.5 秒、Text 間のインターバルは 5 秒である。
コマンドがセットされると所定のクールダウンタイムがセットされ、 一定時間はコマンドの再送出を行わない。 これにより、LTが頻繁に頭出しをするような状況でコマンドが実行されすぎないようにできる。
主要クラス・インスタンス
クラス PlayerAvatar (avatar.PlayerAvatar)
BigWorld.player() の返り値として、自プレイヤーに関する状態を内包したインスタンスを取得できる。 通常の場合、mod がこのクラスのインスタンスを直接作成することはない。
メソッド | 概要 |
---|---|
isObserver() | プレイヤーがオブザーバーかどうかを返す。 |
プロパティ | 概要 |
---|---|
playerVehicleID | プレイヤーの車輌識別子 (VehicleID) 。 |
guiSessionProvider | BattleSessionProvider のインスタンス。 |
クラス BattleSessionProvider (gui.battle_control.battle_session.BattleSessionProvider)
クライアントの様々な状態を保有するコンテナ。 唯一のインスタンスが g_sessionProvider であるが、 0.9.17 の改定で直接インポートできなくなった(方法はあるのかもしれないが)。 プロパティ BigWorld.player().guiSessionProvider でインスタンスを取得できる。
プロパティ | 概要 |
---|---|
shared | クラス SharedControllersLocator のインスタンス。セッション用に作成される各共有コントローラをプロパティとして保持する。 |
メソッド | 概要 |
---|---|
getArenaDP() | クラス ArenaDataProvider のインスタンスを取得する。 |
クラス ArenaDataProvider (gui.battle_control.arena_info.arena_dp)
メソッド | 概要 |
---|---|
getPlayerVehicleID() | 自車輌のIDを取得する。 |
getAllyTeams() | 味方のチームIDの配列を取得する。自チームIDを得るには getAllyTeams()[0] とする。 |
isAllyTeam(vID) | 指定の車輌 (vID) が自チームかどうかを調べる。 |
isSquadMan(vID) | 指定の車輌 (vID) が自分の小隊に所属しているかどうかを調べる。 |
getVehiclesInfoIterator() | クラス VehicleArenaInfoVO のインスタンスを返すイテレータ。 |
クラス VehicleArenaInfoVO (gui.battle_control.arena_info.arena_vos)
戦闘中の車輌の各種情報を保持するクラス。
メソッド | 概要 |
---|---|
isAlive() | 車輌が生存しているかどうかを返す。 |
プロパティ | 概要 |
---|---|
vehicleID | 車輌ID。 |
team | 車輌が所属するチームのID (味方または敵) 。 |
セッション用に作成される各共有コントローラをプロパティとして保持する。
プロパティ | 概要 |
---|---|
chatCommands | チャット用のコントローラ ChatCommandsController への参照。 |
クラス ChatCommandsController (gui.battle_control.controllers.chat_cmd_ctrl.ChatCommandsController)
チャットコマンド (ラジオチャットやミニマップクリックなど) を制御するクラス。
メソッド | 概要 |
---|---|
sendCommand(cmdName) | cmdName で指定したチャットコマンドを実行する。有効なコマンド名は、例えば HELP(F7) であればCHAT_COMMANDS.HELPME.name() のようにして取得できる (CHAR_COMMANDS はモジュール chat_shared で定義されている) 。 |
sendAttentionToCell(cellIdx) | cellIdx で指定した位置のミニマップクリックを実行する。 |
クラス BattleEntry (messenger.gui.Scaleform.battle_entry.BattleEntry)
戦闘中のチャットメッセージ表示を制御するクラス。 MessengerEntry.g_instance.gui でインスタンスを取得できる。
メソッド | 概要 |
---|---|
addClientMessage(self, message, isCurrentPlayer): | message をチャット欄に表示する。 isCurrentPlayer はオプション。True の場合、背景色が BROWN になる。デフォルトは False で BLACK。 |
プロパティ | 概要 |
---|---|
channelsCtrl | クラス BattleControllers のインスタンス。 |
クラス BattleControllers (messenger.gui.scaleform.channels.BattleControllers)
戦闘中のチャットチャンネル群を制御するクラス。 MessengerEntry.g_instance.gui.channelsCtrl から取得できる。
メソッド | 概要 |
---|---|
getControllerByCriteria(criteria) | criteria で指定した条件に適合するチャンネルコントローラを取得する。 criteria はクラス IEntityFindCriteria (モジュール messenger.proto.interfaces) のサブクラスであることが期待される。 criteria のメソッド filter 内でチャンネルの適合条件を指定する。
適合するチャンネルが見つかれば、チャンネルコントローラとしてクラス TeamChannelController, CommonChannelController, SquadChannelController (いずれも IChannelController のサブクラス) のインスタンスを返す。 |
クラス IEntityFindCriteria (messenger.proto.interfaces.IEntityFindCriteria)
チャンネルコントローラの検索条件を指定するクラスのインターフェース定義。
メソッド | 概要 |
---|---|
filter(channel) | channel に対して適合の真偽を返すメソッド。 クラス BattleControllers のメソッド getControllerByCriteria などから呼び出される。 channel には ChannelEntity のサブクラスのインスタンスが与えられる。 |
クラス ChannelEntity (messenger.proto.entities.ChannelEntity)
チャンネルを表すクラス。
メソッド | 概要 |
---|---|
getProtoType() | チャンネルのタイプを返す。 戦闘中のチャットチャンネルであれば PROTO_TYPE.BW_CHAT2 である。 |
getProtoData() | チャンネルの設定データを返す。 戦闘チャットの種別は getProtoData().settings で取得でき、BATTLE_CHANNEL.TEAM, BATTLE_CHANNEL.COMMON, BATTLE_CHANNEL.SQUAD のいずれかの値をとる。 |
クラス TeamChannelController, CommonChannelController, SquadChannelController (messenger.gui.scaleform.channels.bw_chat2.battle_controllers.*)
チームチャット、全体チャット、小隊チャットを制御するチャンネルコントローラ。
メソッド | 概要 |
---|---|
sendMessage(message) | チャットチャンネルに message を送る。 スーパークラスの BattleLayout (messenger.gui.scaleform.channels.layout.BattleLayout) で定義されている。 |
メソッド | 概要 |
---|---|
as_showS() | 6感発動時のflashオブジェクトを実行するために呼び出される。スーパークラスの SixthSenseMeta (gui.Scaleform.daapi.view.meta.SixthSenseMeta) で定義されている。 |
クラス VehicleType (items.vehicles.VehicleType)
プロパティ | 概要 |
---|---|
name | 車輌の識別名 (文字列)。 |
compactDescr | 車輌データの概要。車輌タイプや搭載モジュール (履帯、エンジン、燃料タンク、無線機、砲塔、砲) などの情報を保持する構造体 (バイナリデータ)。情報を取り出すにはモジュール items.vehicles 内の関数が利用できる。 |
クラス ClientArena (ClientArena.ClientArena)
avatar_getter.getArena() でインスタンスを取得できる。
プロパティ | 概要 |
---|---|
arenaType | マップ情報。クラス ArenaType |
guiType | 戦闘モードのID (int)。 |
クラス ArenaType (ArenaType.ArenaType)
avatar_getter.getArena().arenaType でインスタンスを取得できる。
プロパティ | 概要 |
---|---|
name | マップの名称 (I18N文字列)。日本語クライアントの場合、日本語名になる。 |
geometryName | マップの識別名。リプレイファイル名などに表示される名称。 |
boundingBox | マップ範囲。地図上で左下と右上の座標。各座標は長さ2の配列 [X, Y]。 |
クラス AvatarInputHandler (AvatarInputHandler.AvatarInputHandler)
プロパティ | 概要 |
---|---|
ctrlModeName | 現在の制御モードの名称 (文字列)。'arcade', 'strategic', 'sniper', 'postmortem' など。文字列のリストは avatar_helpers.aim_global_binding.CTRL_MODE_NAME で定義されているが直接は利用できない。 |
モジュール
モジュール avatar_getter (gui.battle_control.avatar_getter)
関数 | 概要 |
---|---|
getPlayerTeam(avatar) | プレイヤーのチームを取得する。 avatar はオプション。 |
getPlayerVehicleID(avatar) | プレイヤーの車輌IDを取得する。 avatar はオプション。 |
getVehicleTypeDescriptor(avatar) | プレイヤーの車輌定義情報 (クラス items.vehicles.VehicleDescriptor のインスタンス) を取得する。 avatar はオプション。そのプロパティ type には車輌タイプ情報 (クラス items.vehicles.VehicleType のインスタンス) が保持されている。 |
getArena(avatar) | プレイヤーの現在の戦闘に関する状態 (クラス ClientArena のインスタンス) を取得する。 avatar はオプション。 |
getOwnVehiclePosition() | プレイヤー車輌の位置情報 (座標) を取得する。長さ3の配列 [X, Z, Y]。 |
getInputHandler() | AvatarInputHandler (AvatarInputHandler.AvatarInputHandler) のインスタンスを取得する。 |
isPlayerOnArena(avatar) | プレイヤーが戦闘中かどうかを調べる。 avatar はオプション。 |
setForcedGuiControlMode(value, stopVehicle, enableAiming, cursorVisible) | プレイヤーの GuiControlMode を設定する。 stopVehicle, enableAiming, cursorVisible はオプション。 value が True のとき GUI_CTRL_MODE_FLAG.CURSOR_ATTACHED が、False のとき GUI_CTRL_MODE_FLAG.CURSOR_DETACHED がセットされる。 |
getForcedGuiControlModeFlags(avatar) | 指定の avatar の GuiControlMode を取得する。avatar はオプション。指定しない場合は自プレイヤー。 |
モジュール minimap_utils (gui.battle_control.minimap_utils)
関数 | 概要 |
---|---|
makeCellIndex(localX, localY) | ローカル座標 (localX, localY) を cellIndex (int) に変換する。cellIndex はミニマップ上のセル位置を表す。 |
getCellName(cellIndex) | cellIndex に対応するセル名を取得する。 |
モジュール SystemMessages (gui.SystemMessages)
関数 | 概要 |
---|---|
pushMessage(text, type, priority) | 通知センター (Notification Center) にテキストを表示する。 type, priority はオプション。 |
モジュール items.vehicles
関数 | 概要 |
---|---|
getVehicleClass(compactDescr) | 車輌クラス名を取得する。車輌クラス名は VEHICLE_CLASS_TAGS で定義されており、'lightTank', 'mediumTank', 'heavyTank', 'SPG', 'AT-SPG' のいずれか。 |
BigWorld 内のモジュール
モジュール BigWorld
関数 | 概要 |
---|---|
time() | 現在の戦闘時刻 (秒) を返す。 |
player() | クラス PlayerAvatar のインスタンスを返す。 |
callback(time, function) | time 秒経過後にコールバック関数 function を実行する。 |
モジュール ResMgr
クラス DataSection
DataSection は XML データ構造に対する読み書きの制御を行う。既存のファイルを開く場合は ResMgr.openSectin() を使用する。 メソッドとして __getitem__ などが定義されており、辞書型オブジェクトと同じように obj['key'] のような形式でデータ構造にアクセスできる。
メソッド | 概要 |
---|---|
has_key(key) | サブセクションの中に key で指定された名前があるかどうかを調べる。 |
items() | セクションの子要素をタプル (name, DataSection) のリストとして返す。 |
プロパティ | 概要 |
---|---|
asBool | DataSection の値を boolean に変換する。読み出しの場合、大文字小文字を無視して文字列が "true" と解釈される場合は 1 を、それ以外の場合は 0 を返す。書き込みの場合は、0 が与えられれば "false" を、それ以外の場合は "true" に設定する。 |
asFloat | DataSection の値を float に変換する。読み出しの場合、トップレベルから文字列を float として解釈を試みる。失敗した場合は 0 を返す。書き込みの場合は、トップレベルの文字列を float の文字列表現で置き換える。子のノードには影響しない。 |
asInt | DataSection の値を int に変換する。読み出しの場合、トップレベルから文字列を int として解釈を試みる。失敗した場合は 0 を返す。書き込みの場合は、トップレベルの文字列を int の文字列表現で置き換える。子のノードには影響しない。 |
asString | DataSection のバイナリデータを文字列にカプセル化したもの。読み出しの場合、すべての子セクションが含まれる。書き込みの場合、以前にアクセスした子セクションが無効になることがある。使用には注意すること。メソッド copy を使用してデータセクションをコピーするのがよい。 |
メンバ関数
関数 | 概要 |
---|---|
openSection(resourceID, newSection) | resourceID で指定されたリソースを読み込み、リソースをクラス DataSection のインスタンスとして返す。読み込んだリソースはキャッシュされる。newSection はオプション。newSection が True の場合、新規のセクションとして開く。デフォルトは False。 |
purge(resourceID, recurse) | resourceID で指定されたリソースのキャッシュを廃棄する。recurse はオプション。recurse が True の場合、再帰的に廃棄する。デフォルトは False。 |