Module System > Document by Jik (1)


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

M&B Module System Documentation

v0.8時代に作成されたWinter氏によるModule Systemの解説に、
v1.010に合わせてJIK氏が修正を加えたものです。<英語版DLページ>

<内容>
マップアイコンの編集(街、プレイヤー、etc)
新しいパーティの作成(街、兵士、etc)
新しい兵士の作成
アップグレードツリーの編集
Tavernを例としたシーンの作成とゲームエディタの使い方
会話などダイアログの作成
ダイアログや変数を用いたクエストの作成
トリガーによるパーティの登場
フォーラムより。フィードバックを歓迎しています。)

v1.010のモジュールシステムに対応しており、
劇的なシステムの変更などは無いものの、MOD作成初心者には非常に良いチュートリアルです。
ただし、今のところ未完成です。今後は未完成部分の完成とslotの解説を追加する予定とのこと。

PART4-6へ(リンク)
PART7-10へ(リンク)





PART1 イントロダクション(Getting Started)

1.1 モジュールシステム(Module System)とは?

M&Bのモジュールシステムとは、M&Bの内容を追加、編集するためのpythonスクリプトです。
これは公式で使われてるのと同じもので、モジュールシステムを利用することで新しい部隊、キャラクター、クエスト、ダイアログ等を追加/編集することができます。

ただしM&Bはpythonスクリプトを直接に読み込むことはせず、実際にはpythonスクリプトからtxtファイルを作成してそれを読み込んでいます。
理論上全てのmoddingはこのtxtの編集を通じて行えますが(実際、直接編集するmodderもいますが)正直なところこのtxtは人間が読めるように書かれていません。

現実的なモジュール作成の方法としては今のところ2つの方法があります。
1つめは公式の提供しているモジュールを利用すること。もう1つはEffidian氏による非公式のモジュールエディタを利用すること。
ただし後者はサポートが途切れて現在のバージョンには適応していません。(v7.5.1など旧verには対応しています。)
この文書ではオフィシャルの提供するモジュールの編集を扱います。

1.2 環境の準備

モジュールはpythonスクリプトで出来ているため、編集者もpythonをインストールする必要があります。
Python.orgのダウンロードページ(http://www.python.org/download/)
色々有りますが、Windows向けのv2.6.1だけDLすれば事足ります。

Pythonのインストール後、環境変数を設定します。
Win9Xの場合:Autoexec.batを編集します。
pythonをインストールしたフォルダが”C:\Python24”なら、
“PATH=C:\Python24;%PATH%”を追加します。

WinXP/Vistaの場合:マイコンピュータを右クリックしてプロパティを開き、「詳細設定」タブの中の「環境変数」をクリックします。
1.「システム環境変数」をスクロールダウンして変数:Parhを探します。
2.「編集」ボタンを押すと「システム変数の編集」ウィンドウが開きます。
3.「変数値」の最後尾に”;C:\Python26”を加えます。

1.3 モジュールシステムの入手

最新(v1.010)のモジュールシステムは公式のフォーラムからDLできます。
http://www.taleworlds.com/download/mb_module_system_1010_0.zip
(訳注:公式のフォーラムはかなり細かく分かれています。
モジュールシステムのスレッドは公式TOP->Forum->Module Development->The Forge - Mod Developmentの中にあるようです。)

1.4 モジュールシステムファイル

モジュールシステム内のファイルを見てみましょう。pythonファイル(拡張子.py)は名前の前頭語によって4種類に分かれています。

* header_ * process_ * ID_ * module_

最初の2つ(header_とprocess_)はモジュールシステムの実行に不可欠です。弄らないのが賢明でしょう。
3番目(ID_)はモジュールをビルドする際の一時ファイルです。消去してもモジュールシステムが再生成しますので問題ありません。
4番目(module_)はモジュールの内容に関するファイルです。主にこれを編集します。

1.5 新しいモジュールの作成

次に進む前に、自分のモジュールのためのフォルダを作りましょう。

Mount&Blade\Modules\を開きます。そこにある「Native」というフォルダは公式のモジュールです。
とりあえずModules\にMyNewModuleというフォルダを作り、その中にNativeの中身をコピーします。

さて新しいモジュールをテストします。M&Bを起動してMyNewModuleを選択し起動します。
MyNewModuleの中身はNativeからのコピーなので、ゲーム内容もNativeと同じのままです。

次に、モジュールシステムののビルド先を設定します。

module_info.pyをテキストエディタ等で開き、その中の
export_dir = "C:/Program Files/Mount&Blade/Modules/Native/"を
export_dir = "インストール先のパス/Mount&Blade/Modules/MyNewModule/"に書き換えます。

もしMyNewModule/内にconversation.txtがあればそれを削除しておきます。
build_module.batを実行するとコマンドプロンプトが開き下記のメッセージが表示されます。

Code: [Select]
Initializing...
Compiling all global variables...
Exporting strings...
Exporting skills...
Exporting tracks...
Exporting animations...
Exporting meshes...
Exporting sounds...
Exporting skins...
Exporting map icons...
Creating new tag_uses.txt file...
Creating new quick_strings.txt file...
Exporting faction data...
Exporting item data...
Exporting scene data...
Exporting troops data
Exporting particle data...
Exporting scene props...
Exporting tableau materials data...
Exporting presentations...
Exporting party_template data...
Exporting parties
Exporting quest data...
Exporting scripts...
Exporting mission_template data...
Exporting game menus data...
exporting simple triggers...
exporting triggers...
exporting dialogs...
Checking global variable usages...
______________________________
Script processing has ended.
Press any key to exit. . .

何事もなく終わったなら、おめでとうございます!あなた自身のモジュールが誕生しました!

もしエラーを吐いた場合はこれまでのステップのどこかで見落としかミスをしています。
どうしても困った場合はフォーラムの検索機能で類似の問題に関するスレッドを探してください。
大体の問題とその解決策は提示されています。

※訳注:module_info.pyの中にも書いてありますが、module_info.pyでのディレクトリ指定はバックスラッシュ(\)ではなく
フォワードスラッシュ(/)を使わないとエラーを吐きます。




PART2 モジュールシステムの編集(Editing the Module System)


モジュールシステムの改造手順をおさらいします。
1)モジュールファイル(module_*.py)を編集する
2)build_module.bat を実行し、モジュールをビルドする
3)ビルド時にエラーを吐かなければM&Bを起動してテストする
※変更によってはニューゲームが必要です

2.1 モジュールファイルの個人化
最初にMOD選択画面での画像を差し替えて、自分の物らしくします。
対象となるmain.bmpはMyNewModuleフォルダに入っています。
これを変更するとMOD変更時に分かりやすくて便利です。

DDSファイルを編集できるなら、メニューの背景画像に手を加えるのも良いでしょう。
背景となるbg2.ddsは Mount&Blade/Textures/内にあります。
これをMount&Blade/Modules/MyNewModule/Textures/に移動して編集することで違う背景に出来ます。
pic_mercenary.ddsはメインメニューでの画像です。

この辺りは後からでも出来るので、方法だけ覚えて先に進みましょう。

2.2 モジュールファイルの編集

モジュールシステムではゲーム上のオブジェクトのコレクションにPythonのリストを使っています。
(リストは`[`で始まり、カンマで区切られた要素を含み、`]`で終わります。)

更にそのリストの要素としてタプルを含んでいます。
(タプルは`(`で始まり、カンマで区切られた要素を含み、`)`で終わります。)

例えばmodule_map_icons.pyを開くと下の文章があります。
 map_icons = [
 ("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0),
 ("player_horseman",0,"player_horseman", avatar_scale, snd_gallop, 0.15, 0.173, 0),
 ("gray_knight",0,"knight_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
 ("vaegir_knight",0,"knight_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
 ("flagbearer_a",0,"flagbearer_a", avatar_scale, snd_gallop, 0.15, 0.173, 0),
 ("flagbearer_b",0,"flagbearer_b", avatar_scale, snd_gallop, 0.15, 0.173, 0),
 ("peasant",0,"peasant_a", avatar_scale,snd_footstep_grass, 0.15, 0.173, 0),
 ("khergit",0,"khergit_horseman", avatar_scale,snd_gallop, 0.15, 0.173, 0),
 ("khergit_horseman_b",0,"khergit_horseman_b", avatar_scale,snd_gallop, 0.15, 0.173, 0),
 ...

ここでmap_iconsはリストとして宣言されている一方、リストの各要素
(例えば『("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0)』)はタプルです。

各タプルの構造は各モジュールファイルの先頭に記されています。
map_iconsでは
1 ) マップアイコンのid(名前)
 他のファイルからの参照に用います。
 また接頭語 icon_ が自動的に付与されます。
2 ) アイコンのフラグ
 header_map_icons.py に利用可能なフラグの表があります。
3 ) Mesh の名前
 map_icon_meshes.brf、map_icons_b.brf、map_icons_c.brfに利用可能なリストがあります。
 これらBRFファイルは Mount&Blade\CommonRes にあります。
4 ) Meshのスケール
5 ) サウンドid
6 ) フラッグアイコンのx座標
7 ) フラッグアイコンのy座標
8 ) フラッグアイコンのz座標

これに例のタプル("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0)を当てはめると、下のようになります。
1 ) マップアイコンのid = "player"
2 ) マップアイコンのフラグ = 0
3 ) Mesh の名前 = "player"
4 ) Meshのスケール =  avatar_scale
5 ) サウンドid =  snd_footstep_grass
6 ) フラッグアイコンのx座標 = 0.15
7 ) フラッグアイコンのy座標 = 0.173
8 ) フラッグアイコンのz座標 = 0

他のモジュールファイルでも同様に、先頭にあるオブジェクトの構造に関する記述を読むことで内容を理解できます。

2.3 新しいオブジェクトの追加

マップアイコンのタプルの構造が分かったので、いよいよ自分の新しいマップアイコンを追加します。

map_icons = [
("player",0,"player", avatar_scale, snd_footstep_grass, 0.15, 0.173, 0),
("player_horseman",0,"player_horseman", avatar_scale, snd_gallop, 0.15, 0.173, 0),
.
.
.
("banner_125",0,"map_flag_f20", banner_scale,0),
("banner_126",0,"map_flag_15", banner_scale,0),
]

新しいオブジェクトはリストの内側に追加される必要があります。リストの最後列を一行開けてそこに追加することにします。既存のオブジェクトをコピー&ペーストし、それに手を加えると簡単です。
ここでは("town",mcn_no_shadow,"map_town_a", 0.35,0)をコピーして最後に追加します。

...
("banner_126",0,"map_flag_15", banner_scale,0),
("town",mcn_no_shadow,"map_town_a", 0.35,0) ,
]

次はこれに新しい名前をつけます。”new_icon”としておきます。
このアイコンはフラグに0ではなく mcn_no_shadowが入っています。mcn_no_shadow の効果は「このアイコンは地面に影を落とさない」です。今回はこれを0にしておきます。
...
("banner_126",0,"map_flag_15", banner_scale,0),
("new_icon", 0 ,"map_town_a", 0.35,0),
]

Mesh は利用する3Dモデルの設定です。ここでは”map_town_a”になっているのを”City”にします。
“City”は現在使われていないので判別しやすいのです。
次のスケールは、アイコンを何倍の大きさで表示するかを表しています。ここではtownとの違いが際立つように0.35から2に変更します。
...
("banner_126",0,"map_flag_15", banner_scale,0),
("new_icon",0, "City" , 2 ,0),
]

次節は、今作ったアイコンを私用する新たなパーティを作成するため、module_party.pyを編集します。
パーティがアイコンを利用するためには、アイコンを”参照”する必要があります。
とりあえずここまでで一度モジュールをビルドして構文エラーをチェックしましょう。
エラーの確認のためにビルドするのはナイスアイデアなのです。

2.4 ゲームオブジェクトの参照

module_parties.pyを開きます。
幾つかの定数が宣言された後に parties = [ で始まるPythonのリストがあります。
定数(ex.pf_town = pf_is_static|pf_always_visible|pf_show_faction|pf_label_large)は複数のフラグの繰り返しを楽にしてくれます。定数に関しては後で後述します。

見ての通り、module_partiesのタプルの構造はmodule_iconsとは若干異なっています。
まずはpartiesの構造を詳しく見ていくことにします。
例として下のタプルを取り上げます。このタプルはSargothをマップ上に配置しています。
("town_1","Sargoth", icon_town|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1.55, 66.45),[], 170),

タプルの構造を見てみます。
1)パーティID。 他のファイルからの参照に使います。
  前頭語 p_ が自動的に付与されます。
2) ゲーム上で表示されるパーティの名前。
3)パーティのフラグ。1つ目のフラグは必ずそのパーティのアイコンを示す必要があります。
  header_parties.pyに利用可能なフラグの表があります。
4)メニュー。v0.730以降使用されておらず、使用は非推奨の状態です。
5) パーティテンプレート。このパーティが属するパーティテンプレートのIDです。
  デフォルトはpt_noneです。
6)ファクション。module_factions.pyで宣言されています。
7)パーソナリティ。header_parties.pyにこのフラグの説明があります。
8)AIの行動。マップ上でAIがどう行動するかを示します。
9)AIのターゲットパーティ。AIのターゲットを示します。
10)初期の座標。
11)スタックしている部隊のリスト。 三つの要素を含みます。
11.1)部隊のID。module_troops.pyに利用可能な表があります。
11.2)スタックしている部隊の数。
11.3)メンバーフラグ。無くてもOKですがpmf_is_prisonerを入れると囚人扱いになります。
12)パーティの向いている角度(無くてもOK)

Sargothの例と比較すると、
("town_1","Sargoth", icon_town|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1.55, 66.45),[], 170),


1) パーティID = “town_1”
2)パーティの名前 = “Sargoth”
3)フラグ = icon_town|pf_town
4)メニュー = no_menu
5)テンプレート = pt_none
6)ファクション = fac_neutral
7) パーソナリティ = 0
8)AIの行動 = ai_bhvr_hold
9)AIのターゲット = 0
10)初期配置 = (-1.55, 66.45)
11)部隊のスタック = [](無し)
12)向き = 170

3)を見ると、Sargoth はmodule_icons.py からアイコン”town”に前頭語icon_ をつけて参照しています。
前頭語はシステムに「どのモジュールファイルからなのか」を示すために用いられています。

ex. mocule_icons:icon_ , module_factions:fac_ , module_parties:p_ など。
各モジュールファイルに対応する前頭語があります。

ではパーティの構造を知った上で、自分の新しいパーティを追加しますが、その前に注意事項があります。
module_partiesや他のいくつかのモジュールファイルでは、リストの最後に追加するとエラーを起こします。
そういう場合は注意書きがコードの中に書かれています。

module_parties.pyでは”town_1”と”castle_1”の間への追加が推奨されています。
これはmodule_constants.pyで定義されています。これについては後述します。

では”town_1”をコピーして”town_18”の直後にペーストします。

...
("town_18","Narra", icon_town_steppe|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-22.6, -82),[], 135),

##JIK's Test Area
("town_1","Sargoth", icon_town|pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1.55, 66.45),[], 170),
##End of JIK's Test Area

# Aztaq_Castle
# Malabadi_Castle
("castle_1","Culmarr_Castle",icon_castle_a|pf_castle, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0,(-69.2, 31.3),[],50),.
...

表記とコメントについて触れておきます。
使用する部位をコメント(#で始まる行)で囲いだし、私(訳注:筆者であるJIK氏)の名前つきで印をつけてあります。
こうすると検索で便利ですし、後から読んでも何をしているか分かりやすくなります。
このチュートリアルではこういった点にも触れておきます。習慣にしましょう。

では編集していきます。
パーティIDを”town_1”から”mod_town”へ、パーティの名前を”Sargoth”から”Mod_Town”へ変更します。

タプルを見ていくと幾つかのことが読み取れます。
1)このパーティを参照するためにはパーティIDに前頭語p_をつけて”p_mod_town”を使います。
2)ゲーム内では”Mod Town”が表示されます。
3)このパーティはicon_townとフラグpf_town(街の共通設定のフラグ)を利用しています。
  フラグは次に幾つか変更します。
4)Mod Townのファクションはneutralです。
5)このままだとMod TownはSargothとまったく同じ場所に出現します。なので変更します。

##JIK's Test Area
( "mod_town" , "Mod_Town" , icon_new_icon |pf_town, no_menu, pt_none, fac_neutral,0,ai_bhvr_hold,0, (-1, -1) ,[], 45 ),
##End of JIK's Test Area

初期配置を(-1,-1)に、方角を45に、アイコンを”new_icon”に変更しました。
こうすることで問題なく出現します。

セーブしてbuild_moduleを実行します。うまく行っていればマップの中心付近に新しい街が出現します。
失敗した場合、文法とスペリングをチェックしましょう。カンマと括弧の位置に気をつけてください。

街のゲームメニューの設定をしていないので、このままでは街に行ってもマトモに機能しません。
ゲームメニューの設定は少々ややこしいので後述することにして、とりあえずここでは新しい街を作るまでにしておきます。

MOD作成の基礎はこれでおしまいです。Chapter3以降は各モジュールファイルについて見ていきます。

[前頭語リスト]
fac_ -- module_factions.py
icon_ -- module_map_icons.py
itm_ -- module_items.py
mnu_ -- module_game_menus.py
mno_ -- module_game_menus.py  ――module_game_menu内の各オプションへの参照
mt_ -- module_mission_templates.py
psys_ -- module_particle_systems.py
p_ -- module_parties.py
pt_ -- module_party_templates.py
qst_ -- module_quests.py
script_ -- module_scripts.py
scn_ -- module_scenes.py
spr_ -- module_scene_props.py
str_ -- module_strings.py
trp_ -- module_troops.py
skl_ -- module_skills.py
module_dialogs.pyは直接参照されることがないので前頭語もありません。

PART3 兵士(Module Troops)


この章ではmodule_troops.pyを扱います。
module_troopsは一般の部隊、ヒーロー、チェストと街のNPCを定義し、顔、能力値とインベントリを加えて完成します。
新しいキャラ、兵種を追加するときはこのファイルを編集します。

3.1 module_troopsの内容

最初の数行は武器のproficienciesの計算などが記述されています。
この辺はアンタッチャブルなのとPythonのリストの域を超えるために扱わず、
とりあえず troops のリストまで飛ばします。

ここにはプレイヤーや他の兵士に関するタプルがあり、
すぐ下にArenaの相手として出てくる戦士に関するタプルがあります。
これを例として一般兵のレベルアップを見ていきます。
["novice_fighter","Novice Fighter","Novice Fighters",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,mercenary_face_1, mercenary_face_2],

これは”novice fighter”君に関する表記です。彼を一言で表せばザコです。
ではこのタプルの意味を見ていきます。
1)兵士のID。他のファイルからの参照に用います。
2)兵士の名前。
3)複数形での兵士の名前。
4)兵士のフラグ。tf_guarantee_* はその種類の装備がインベントリに存在しているとき必ず身に着けることを保証します。
  これをはずすと、その種類の装備をつけずに登場することがあります。melee武器だけは持っている限り必ず保証されます。
5)シーン。これはヒーローユニットにだけ適用され、ヒーローが登場するシーンを指定します。
  ex. scn_reyvadin_castle|entry(1) は reyvadin Castleの出現ポイント1にヒーローを登場させます。
6)予約。現在使われていません。reservedか0だけが入ります。
7)ファクション。前頭語fac_を用います。
8)インベントリ。兵士のインベントリにあるアイテムのリストです。一般兵はこのリストの中からランダムに装備を選びます。
9)Attribute。兵士のAttributeの値とレベルです。プレイヤーに対してと同様に働きます。
10)武器のProficiencies。wp(x)は値xの周りでランダムにWeapon Prodicienciesを生成します。
  ex.弓のエキスパートだが他の武器のproficienciesは60くらいの兵士の記述はwp_archery(160)|wp(60) となります。
11)Skills。プレイヤーのスキルと同様です。
  但し兵士はキャラクターレベル毎にAttributeポイントとSkillポイントを1ポイントづつ得て、それをランダムに割り振ります。
12)顔コード1。顔エディット画面でCtrl+Eを押すことで顔コードを出力できます。(エディットモード)
13)顔コード2。ヒーローユニットには無効で一般兵にだけ適用されます。一般兵の顔は顔コード1と2のどちらかからランダムに決定されます。

Novice_fighterのタプルを当てはめてみます。
1)ID = “novice_fighter”
2)名前 = “novice_fighter”
3)名前の複数形 = “novice_fighters”
4)フラグ = tf_guarantee_boots|tf_guarantee_armor
5)シーン = no_scene
6)予約 = reserved
7)ファクション = fac_commoners
8)インベントリ = [itm_sword,itm_hide_boots]
9)Attributes = str_6|agi_6|level(5)
10)Weapon Proficiencies = wp(60)
11)Skills = knows_common
12)顔コード1 = swadian_face1
13)顔コード2 = swadian_face2

さて注意点が3つあります。
フラグ tf_guarantee_armor が付いていますが彼は鎧を持っていません。
しかしこれは無意味なフラグではなく「ゲーム中に手に入れたら必ず装備する」ことを指示しています。

STRとAGIは6とされていますがこれはLv1でのAttributeです。
実際にはLv5で登場するので、その分のポイントがランダムに加算されて現れます。

スキル knows_common はスキルの集合で、module_troops の中で先に定義されています。
上にスクロールして探してみると、下記の定義が見つかります。
knows_common = knows_riding_1|knows_trade_2|knows_inventory_management_2|knows_prisoner_management_1|knows_leadership_1

ではknown_commonの意味を見ていきます。
各スキルのレベルはRiding=1、Trade=2、Inventory Management=2、Prisnor Management=1、Leadership=1です。
known_commonは「定数」です。定数は色々な値、ID、他の定数やオブジェクトを表すことができます。

この例だと known_commonは
knows_riding_1|knows_trade_2|knows_inventory_management_2|knows_prisoner_management_1|knows_leadership_1
と定義され、スキルの欄にknows_commonを代入すると定義文を代入したのと同様に働きます。

では次の兵士の記述を見てみます。
["regular_fighter","Regular Fighter","Regular Fighters",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_hide_boots],
str_8|agi_8|level(11),wp(90),knows_common|knows_ironflesh_1|knows_power_strike_1|knows_athletics_1|knows_riding_1|knows_shield_2,mercenary_face_1, mercenary_face_2],

これを見ると”novice fighter”より少し強く、スキルもknows_common以上の物を持っていることが分かります。
次は”novice fighter”がLv11になったら”regular fighter”へアップグレード出来るようにします。

3.2 兵士のアップグレード
アップグレード経路のリストは module_troops の一番下にあります。
アップグレードの選択肢は upgrade(troops) によって定義されます。
最初のIDはアップグレード元、二番目がアップグレード先です。
ex. upgrade(troops,"farmer", "watchman") は farmer から watchman への流れを示しています。

アップグレードの演算は2通りあります。
upgrade(troops,"source_troop", "target_troop_1"),
upgrade2(troops,"source_troop", "target_troop_1", "target_troop_2"),
upgrade2はアップグレード先が2つある場合に用います。今のところ3つは出来ません。

“novice fighter”の行は無いので、upgrade(troops,"farmer", "watchman")をコピーしてこのブロックの最後の列にペーストし、”farmer”を”novice_fighter”に、”watchman”を”regular_fighter”に書き換えます。
upgrade(troops,"novice_fighter", "regular_fighter")
これで”novice_fighter”から”regular_fighter”へのアップグレードが可能になりました。
注意:この作業をしているブロックはtroopsのブロックの外にあります。
   またこのブロックの各行末にはカンマがありません。

更に、これから作る新しい兵士の分を追加しておきます。
upgrade(troops,"new_troop", "novice_fighter")
を最後に追加します。

終わったら上にスクロールして
# Add Extra Quest NPCs below this point
がある位置を見つけてください。新しい兵士はここで定義される必要があります。
というわけで"local_merchant"の前に新しい兵士を追加します。

3.3 新しい兵士(troop)の追加
"local_merchant"の前に一行作り、”novice_fighter”をコピー&ペーストして少し手を加えます。
##JIK - new troop entry
[ "new_troop" , "new_troop" , "new_troops" ,tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[ itm_sword_medieval_a , itm_leather_jerkin , itm_skullcap ,itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,mercenary_face_1, mercenary_face_2],

見ての通り、"new troop"君は剣と鎧、ブーツを装備しています。
一方“itm_skullcap”を装備しているかはランダムです。
帽子も必ず装備するようにフラグ tf_guarantee_helmet を追加することにします。

##JIK - new troop entry
["new_troop","new_troop","new_troops",tf_guarantee_boots|tf_guarantee_armor| tf_guarantee_helmet ,no_scene,reserved,fac_commoners,
[itm_sword_medieval_a,itm_leather_jerkin,itm_skullcap,itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,mercenary_face_1, mercenary_face_2],

兵士の能力も変更します。STRとAGIを9に、Lvを4、Weapon Proficiencyを80にします。
##JIK - new troop entry
["new_troop","new_troop","new_troops",tf_guarantee_boots|tf_guarantee_armor|tf_guarantee_helmet,no_scene,reserved,fac_commoners,
[itm_sword_medieval_a,itm_leather_jerkin,itm_skullcap,itm_hide_boots],
str_9|agi_9|level(4),wp(80) ,knows_common,mercenary_face_1, mercenary_face_2],

ここまで出来たらbuild_module.batを実行してエラーを確認しておきます。

3.4 マーセナリ ※この部隊はもう無いので、new_troopを代わりに利用します。

スタート時に1人だと寂しいので、数人の仲間を連れているようにします。
module_parties.pyを開き、”main_party”で始まるタプルを探します。
5人のnew_troopを連れているように変更します。
("main_party","Main Party",icon_player|pf_limit_members, no_menu, pt_none,fac_player_faction,0,ai_bhvr_hold,0,(17,52.5),[(trp_player,1,0) ,(trp_new_troop,5,0) ]),

(trp_new_troop,5,0)をパーティスタックに追加しました。
ここで一度セーブしてビルドします。成功したら新しくゲームを開始しましょう。
5人のnew troopが仲間に入っているはずです。
更に戦闘してnovice fighterやregular fighterへアップグレード出来ることを確認しましょう。

おめでとうございます! あなたは一般兵の編集方法を習得しました!
次節ではヒーローユニット、商人、NPCに手を伸ばします。

3.5 NPC

NPCを見るためにmodule_troops.pyを開きます。
一般兵とよく似ていますが、NPCと商人が持つ最大の違いは フラグ tf_hero の存在です。
このフラグによってMarnidやBorchaは独自のステータスを持てるようになっています。
商人も含め、ゲーム内の全てのユニークNPCはヒーローユニット扱いです。

ヒーローと一般兵の違いを挙げていきます。
1)ヒーローは殺害できない。
  彼らのヘルスは%表示されます。また複製しない限り唯一無二です。
2)ヒーローは1人で1スタックである。
  各ヒーローはその種族の中で唯一の存在なので、複数形の名前を持ちません。
  なのでタプルの3番目の要素は2番目と同一です。
3)ヒーローは兵士タプルで指定されたシーンに登場する
4)味方のヒーローは囚われの身にならない。
  一方プレイヤーは敵のヒーローを捕まえられます。

例としてヒーローのタプルを見てみます。
["npc2","Marnid","Marnid", tf_hero|tf_unmoveable_in_party_window, 0,reserved, fac_commoners,[itm_linen_tunic,itm_hide_boots,itm_club],
str_7|agi_7|int_11|cha_6|level(1),wp(40),knows_merchant_npc|
knows_trade_2|knows_weapon_master_1|knows_ironflesh_1|knows_wound_treatment_1|knows_athletics_2|knows_first_aid_1|knows_leadership_1,
0x000000019d004001570b893712c8d28d00000000001dc8990000000000000000],

これらは我らが心からの友人Marnid君です。
フラグ tf_ hero によってヒーローユニットと定義されています。
またフラグ tf_unmoveable_in_party_window は敵の虜囚とならない、あるいは拠点に置いたり交換したり出来ないことを指示しています。
彼は Happy Boar Inn の 登場ポイント4に登場していましたが、新しいコードでは各地のTavernにランダムに出現するようになりました。
(JIKによる注:このコードは後で解説する必要があるでしょう。)

Marnidは戦闘では非力ですが交易関係のスキルは充実しています。ヒーローとしてスクリプトイベント以外では死ぬことはありません。
また彼はユニークな顔コードを持っています。顔はゲーム内の顔エディターを利用することで変更したりコードを作ったりできます。
これについてはPART10で触れることにします。

Marnidの兵士IDが”npc2”である点に注意しましょう。
参照は常に小文字で行う必要があります。大文字を使うとエラーを吐きます。
なので、他のファイルからMarnidを参照する場合は”trp_npc2”を用います。

タプルの意味が分かるようになったので新しいヒーローを追加します。
# Add Extra Quest NPCs below this point の行を探して、
先に作った”new_troop”の上にMarnidのタプルをコピーします。
分ける必要のない限り、変更点を一箇所にまとめておくのはナイスアイデアです。

コピーしたタプルに手を加えます。
“npc2”を”npc17”に(既にnpc16まで存在しているので)、名前を”Geoffrey”にします。
ついでにMarnidと見た目を変えるために”itm_linen_tunic”を”itm_courtly_outfit”にしておきます。
[ "npc17","Geoffrey","Geoffrey" , tf_hero|tf_unmoveable_in_party_window, 0,reserved,
fac_commoners,[ itm_courtly_outfit ,itm_hide_boots,itm_club],def_attrib|level(6),wp(60),knows_trade_3|knows_inventory_management_2|knows_riding_2,
0x000000019d004001570b893712c8d28d00000000001dc8990000000000000000],

ここまで出来たらビルドします。
エラーを吐かずに成功すればテストにかかりたいのですが、居場所がランダムなので「どこにいるのか分からない」という問題があります。
そこで出現場所を指定します。

town_6(Pravenです)の出現ポイント6を指定することにします。
["npc17","Geoffrey","Geoffrey", tf_hero, scn_town_6_tavern|entry(1) ,reserved,
fac_commoners,[itm_courtly_outfit,itm_hide_boots,itm_club],def_attrib|level(6),wp(60),knows_trade_3|knows_inventory_management_2|knows_riding_2,
0x000000019d004001570b893712c8d28d00000000001dc8990000000000000000],

“scn_town_6_tavern|entry(1)”を追加して再ビルドします。
成功していればPravenのTavernにGeofferey君がいるはずです。
Geofferey君はとりあえずそのままにして、シーン作成の方に移ります。

その前に、これから作るクエストの"役者"を配置しておきます。
まず“costable_hareck”のタプルを探し、Geofferey君の下にコピーします。
後で新しい顔をあて、Mod Townでのクエストのシーンに配置しますが、
その前に彼にユニークなIDを与えます。IDを”hareck”に、フラグを0にしておきます。
["hareck","Constable Hareck","Constable Hareck",tf_hero, 0,reserved,
fac_commoners,[itm_leather_jacket,itm_hide_boots],def_attrib|level(5),wp(20),knows_common,0x00000000000c41c001fb15234eb6dd3f],

3.6 商人 ※これはWinter氏の旧バージョンのままで、テストされていません。
商人はヒーローの特殊形です。tf_hero に加えて tf_is_merchant を持っています。
このフラグはインベントリの中から特別に指定されたもの以外の装備をさせません。
言い換えると、商人は全てのアイテムを受け取れるがその一切を自分で装備せず、商品とします。

商人の例:
["zendar_weaponsmith","Dunga","Dunga",tf_hero|tf_is_merchant,
scn_zendar_center|entry(3),0,fac_commoners,[itm_linen_tunic,itm_nomad_boots],
def_attrib|level(2),wp(20),knows_inventory_management_10,
0x00000000000021c401f545a49b6eb2bc],

これはZendarにいる商人Dungaのタプルですが、Nativeのほかの商人とほとんど同じです。
他との違いはIDと名前、シーン配置、そして顔です。
(訳注:Zendarは旧バージョンに存在した街で、現在のv1.011には存在しません。)

※繰り返しますがこれはテストされていません。新しい商人は”merchants_end”タプルの直前に追加することを推奨します。
商人を追加する手順は少々複雑です。M&Bには「商人のインベントリを毎日更新する」スクリプトがあり、それは商人のタイプごとに存在しています。
そして、そのスクリプトはrange関数を用いています。(range関数:指定した範囲に存在する下位タプルの数を返す関数)

ex. 防具商人のrangeは”zendar_armorer”を下限として含み、”zendar_weaponsmith”を上限として含みません
このため、新しい防具商人は”zendar_weaponsmith”の前に、新しい武器商人は”zendar_tavernkeeper”の前に、新しい財商人は”merchants_end”の前に加える必要があります。
(訳注:range関数は終了位置を結果に含みません。
    例えばrange(1,10)は[1, 2, 3, 4, 5, 6, 7, 8, 9]を返します。)

3.7 チェスト
ゲーム内にはプレイヤーが干渉できる箱がありますが、チェスト兵士はそのインベントリの役割を果たす特殊な兵士です。
チェスト兵士はチェストそのものではありません。あくまでもそのインベントリです。
ゲーム内で見かけるチェストはシーンプロップ、シーンインフォメーション、兵士、ハードワイヤードです。
新しいチェストを作るためには複数のモジュールを編集する必要があり、いささか複雑です。
ここではmodule_troopsに関係するインフォメーションにだけ触れておきます。

チェストの例:
["zendar_chest","Zendar Chest","Zendar Chest",tf_hero|tf_inactive, 0,reserved, fac_neutral,
[],def_attrib|level(18),wp(60),knows_common, 0],

チェストのタプルはどれも殆ど同じです。新しいチェストを作る上で変更する点はID、名前、Lv、スキル、そしてインベントリです。
上述の通り、チェスト兵士はゲーム内のチェストのインベントリとして働きます。
ゆえに、チェスト兵士のインベントリに追加した全てのアイテムはゲーム開始時からチェストの中に存在します。

チェストが機能するためにはチェスト兵士が必要です。しかし他のモジュールファイルにも手を加える必要があります。
これに関しては各ファイルの解説の中で触れることにします。

これでmodule_troopsについての全てを学びました。header_troops.pyには使用可能な他のフラグの表があります。
色々実験をして、準備が出来たら次のPART4に進みましょう。