メインコンテンツにスキップ

ゾーンシート (Zone)

ソーステーブルを作成するときは、必ず公式ソーステーブルの最初の3行をそのままコピーし、4行目以降にデータを入力してください。

列、空行、空セルについて

足りない列は空の値で埋められます。その際ゲームはログ(Player.log)に #source ill-format 警告を出力し、読み込みは続行されます。列の順序が入れ替わっている場合もヘッダー名で自動的に再マッピングされます。とはいえ、公式テーブルのヘッダー行をまるごとコピーしておけば、どちらのケースも最初から避けられます。

id が空の行があると、そこでシートの読み込みが打ち切られます。 それ以降の行はすべて読み込まれず、警告も出ません。意図的でない限り、データの区切りに空行を使わないでください。

空セルは空の値ではありません——ゲームは3行目のデフォルト値にフォールバックします。このシートの既定値は type=ZoneLV=1、chance=100、idBiome=Plaindev=0、image=default です。

3行目のデフォルト値を書き換えれば、それを他のすべての行に適用できます。データは4行目から入力してください。

シートの列

タイプ説明
idテキストゾーンの一意の識別子。バニラのエントリまたは他のModのエントリIDと一致する場合、最後にロードされたシートが他を上書きします。この値にスペースを含めることはできません — 必要に応じて snake_case スタイルを使用してください(例:mymod_zone_funk_house)。
parentテキスト親ノードのID。ニューゲーム時、ゲームは world から再帰的にツリーを構築し、parent が現在のノードと一致するすべての行を子として生成します。ノースティリス大陸にぶら下げたい場合は ntyris を指定します。ゾーンをワールドマップに配置するを参照。
name_JPテキスト日本語の表示名。
nameテキスト英語の表示名。その他の言語については SourceLocalization を使用してください。
typeテキストゾーンのC#型名。既存のZone型またはDLLのZoneサブクラスを使用できます。コードでカスタマイズする場合は、以下のカスタムゾーンタイプを参照してください。
LV整数危険度レベル。ゾーンの基本危険度として書き込まれます。子フロアの危険度は トップゾーンの危険度 + abs(lv) - 1 で算出されます。
chance整数ランダムサイトを抽選する際の重み。random タグと併用した場合のみ意味を持ちます。
factionテキストこのゾーンが属する派閥のID。
value整数ホームランキングリストで使用されるゾーンの価値。lv == 0 かつ value > 0 のゾーンのみがランキング対象になります。
idProfileテキストゾーンプロファイルID。ランダム生成されるマップの作られ方を決めます。マップファイルを読み込むゾーンでは無視されます。ゾーンプロファイルを参照。
idFileテキスト[]マップファイルのベース名。実際に使われるのは最初の要素だけです — ゲームがマップファイルを探す順序を参照。ファイルが見つからない場合はランダムマップが生成されます。
idBiomeテキストバイオームタイプ。既存の BiomeProfile のIDである必要があり、不明な値は例外になります。マップ設定にバイオーム上書きを持つマップファイルは、この列より優先されます。
idGenテキスト未使用。この列を読むコードはゲーム内に存在しません——ダンジョンジェネレーターはC#型の IDGenerator プロパティから決まります。
idPlaylistテキストプレイリスト。lv != 0 のゾーンで空欄の場合は Underground にフォールバックします。現在、カスタムプレイリストにはCWLが必要です。
tagテキスト[]このゾーンに適用されるタグのカンマ区切りリスト。下記の タグリファレンス を参照してください。
costSkyTravel整数スカイトラベル(ムーンゲート)の費用。サバイバルモードでは目的地の条件としても使われます。
cost整数未使用。
dev整数デフォルトのゾーン開発レベル。
imageテキストゾーン選択画面に表示される画像名。ゲーム内蔵の Media/Graphics/Image/Zone/ リソースから読み込まれます。空欄なら default。カスタム画像には対応していません。
pos整数[]ワールドマップ上のゾーン位置。x,y,iconID の形式で指定します。3つの値すべてが必須です——セルが空でない限り、ゲームは3番目の値を無条件に読み取ります。空欄にするとゾーンは -1000,-1000、つまりワールドマップ外に置かれます。iconID の調べ方は下記の ワールドアイコンID を参照してください。
questTagテキスト[]このゾーンで発生可能なクエストタイプ。各項目は タグ/重み の形式です(例:deliver/7,food/8)。プレイヤーの派閥ゾーンの場合は無視されます(固定リストが使われます)。
textFlavor_JPテキストゾーン進入時に表示されるフレーバーテキスト(日本語)。
textFlavorテキストゾーン進入時に表示されるフレーバーテキスト(英語)。その他の言語については SourceLocalization を使用してください。
detail_JPテキストゾーンの説明(日本語)。
detailテキストゾーンの説明(英語)。その他の言語については SourceLocalization を使用してください。

タグリファレンス

tag 列で認識されるタグ:

タグ説明
addMap効果は2つあります。idFile が空でもModパッケージ内のマップファイルを探せるようにすること、そしてロードのたびにゾーンをワールドへ生成すること——つまり既存のセーブデータにも反映されます。親を指定できます:addMap(ntyris)(旧CWL形式 addMap_ntyris も可)。ゾーンをワールドマップに配置するを参照。
randomこのゾーンをワールドマップ上のランダムサイトとして出現させます。重みは chance です。
debug開発モードが有効なときのみ生成/抽選されます。出荷したくないテスト用ゾーンに便利です。
closed閉鎖状態としてマークします。ワールドマップからの進入は zoneClosed で拒否され、ファストトラベル不可、配達先の候補からも除外され、ワールドマップのタイルには閉鎖表示が重ねられます。
returnプレイヤーのホームゾーンでなくても、帰還先として使用できます。
lightプレイヤーの派閥ゾーンでなくても、照明を有効にします。
tech商人のインベントリ背景にテックボックスを使用します。
iconFlagワールドマップのアイコンを旗タイルに強制し、pos のアイコンIDを上書きします。

ワールドアイコンID

pos 列は x,y,iconID 形式です。3番目の値 iconID は、ゲーム内蔵タイルセットのワールドマップアイコンの数値IDです。下のタイルセットにカーソルを合わせて各アイコンのIDを確認し、pos 列で使用してください。

外部スプライトによるカスタムゾーンアイコンは現在サポートされていません。

タイルセットビューアー

さらに、ゾーンの x,y 座標を決定する際に、コンソールコマンド mod.pos を使用して、現在のプレイヤーキャラクターがいるワールドマップの座標を取得することができます。

カスタムゾーンタイプ

C# DLLで定義されたカスタムゾーンタイプを使用できます。

cs
public class Zone_MyFunkHouse : Zone_Civilized
{
    // overrides
}

基本クラスは Zone から派生している必要があり、どの Zone タイプを使用するかは自由に選択できます。

type 列はリフレクションで解決されます。まず本体アセンブリを探し、続いてMod側で登録済みのすべてのアセンブリを型名で走査します(アセンブリが登録されていれば名前空間付きの完全名も使えます)。解決に失敗してもエラーは出ません——ゲームは黙って素の Zone にフォールバックします。カスタム処理がまったく動かない場合は、まず綴りを確認してください。

サブクラス化する際によく使うフック:

メンバー用途
OnVisitNewMapOrRegenerate()マップが初めて生成された、またはインポートされたときに実行されます。手作りマップの後処理に最適です。
OnActivate()プレイヤーがゾーンに入るたびに実行されます。
GetNewZoneID(int level)新しいフロアを作るときにどのゾーン行を使うか。複数階層のゾーンを参照。
StartLV新規生成されるゾーンの初期 lv(既定は 0)。
IDGeneratornon-null を返すとDunGenのダンジョンジェネレーターに切り替わります。
IdProfile / IdBiome / IDPlayList対応するシート列を実行時に上書きします。

マップの作成!

noa氏の引用:

マップ作成(NPCの配置、家具の設置、ブロックのレイアウトなど)は、すべてゲーム内のビルドモード(開発モード)で行います。マップが完成したら、F1キーの「Export Map」機能でエクスポートします。その後、SourceGame.xlsxのZoneシートで既存のゾーンエントリをコピーし、id、name、type、posなどのフィールドを変更し、idFileをエクスポートしたマップのファイル名に設定します。基本的に、ゲームに新しいマップを追加するために必要なのはこれだけです。

以下では、現行ビルドの実際の挙動に沿ってこの流れを掘り下げます。

開発モードに入る

コンソールコマンド mod.elin_dev を使うか、-dev 引数付きでゲームを起動します。mod.elin_dev false で再起動せずに解除できます。

マップを編集する

編集はすべて通常のビルドモードで行います。ビルドモード中に使える開発者用ショートカット:

キー動作
F1デバッグコマンドのレイヤーを開きます(エクスポートコマンドはここにあります)。
F2ゾーンの再生成を強制します——つまりマップファイルを読み込み直します。.z が実際に拾われているかの確認に便利です。
コピーツール中の K / Lマップピース.mp)のエクスポート/インポート。他のマップに貼り付けられる矩形の区画です。マップピースは Map Piece/ に置かれ、ゾーンのマップとは別物です。

マップをエクスポートする

F1 を開いて、次のいずれかを使います:

コマンド結果
Export Zone<ゲームフォルダ>/Package/_Elona/Map/<idFile>.z に書き出します。書き出す前に同名の旧ファイルを Map/Backup/ にコピーします。ゾーンの idFile が空の場合ファイル名は _new.z になりますが、ゲームは意図的にこの名前を読み込みません——エクスポート前に idFile を設定してください
Export Zone(Dialog)同じエクスポートですが、保存先を自分で選べます。
Import Zone(Dialog)任意の .z を選ぶと、ゲームがそれ用の Zone_User と、そこへ通じるテレポーターを足元に作ります。シートを触らずに他人のマップを覗くのに便利です。

エクスポートされるのはプレイヤー作成物だけ

地形(ブロック、床、オブジェクト、橋、屋根、高さ、デカール、装飾……)は常に完全に書き出されます。一方、物とキャラクターは isPlayerCreation フラグが立っているものだけが書き出されます。 マップジェネレーターやデバッグ生成コマンドが置いたものは、エクスポート時に捨てられます。

ビルドモードで自分が設置した物はプレイヤー作成物なので、家具はたいてい残ります。キャラクターは通常残りません。noa氏自身のツールはエクスポート前にマップ上のすべてにフラグを立てており、スクリプトModでも同じことができます:

cs
foreach (var t in EClass._map.things) t.isPlayerCreation = true;
foreach (var c in EClass._map.charas) c.isPlayerCreation = true;
.z ファイルの中身

.z は以下を含むzipアーカイブです:

  • セル単位の地形バイト配列(blocksfloorsobjsheightsbridgesroofBlocks など)
  • map —— シリアライズされた Map オブジェクト。MapConfig(バイオーム上書き、屋内フラグ、シーンプロファイル、LUT、霧、天候……)を含みますが、物のリストは取り除かれています
  • export —— シリアライズされたカード(プレイヤー作成物の物とキャラクター)
  • meta —— 名前、id、tag、そしてエクスポート時のゲームバージョン。古すぎるバージョンは検証に失敗します
  • Texture Replace/ —— そのゾーンのローカルテクスチャ置き換えフォルダ(あれば)

ゲームがマップファイルを探す順序

ゾーンが初めてアクティブ化されるとき、探索順は次のとおりです:

  1. <ゲームフォルダ>/Package/_Elona/Map/<idExport>.z —— idExportidFile[0] に、0 以外のフロアなら _F<lv> サフィックスを付けたもの。_new.z は明示的に除外されます。
  2. そのファイルが存在せず、かつその行の idFile が空でないか addMap タグを持つ場合、有効化されているすべてのModパッケージについて、次の相対パスを順に探します:
    • Maps/<idExport>.z
    • Maps/Zone_<id>@<lv>.z
    • Map/<idExport>.z
    • Map/Zone_<id>@<lv>.z
  3. どれも見つからなければ、idProfile に従ってランダム生成されます。

覚えておく価値のある点が2つあります:

  • Zone_<id>@<lv> という形式(ゾーンのフルネーム)を使えば、行に addMap タグさえあれば idFile を一切書かずにマップを配布できます。
  • 複数のパッケージが同じ相対パスを提供している場合、最後に読み込まれたものが勝ちます。また手順1が最優先なので、Package/_Elona/Map/ に残ったエクスポートファイルはMod内のコピーを覆い隠します——テスト中は削除するかリネームしてください。

Modに同梱する

エクスポートした .z を、Modパッケージのルート直下の Maps フォルダに、ソースシートと並べて置きます:

MyMod/
├─ package.xml
├─ SourceGame.xlsx        (あなたのZone行)
└─ Maps/
   ├─ mymod_funk_house.z
   └─ mymod_funk_house_F-1.z

訪問済みのゾーンは自前のコピーを保持します

プレイヤーが一度ゾーンに入ると、そのマップはセーブデータ内に保存され、以後 .z は参照されません。マップファイルを更新しても、再生成されるまで訪問済みゾーンは変わりません。反復作業中は、新しいセーブで始めるか、ビルドモードで F2 を使ってください。

ゾーンをワールドマップに配置する

仕組みは2つあり、挙動が異なります。

parent —— ニューゲームのみ。 ワールド生成時、ゲームは world の行から再帰し、構築中のノードを parent に指すすべての行を実体化します。したがって parentntyris のような大陸IDを設定すると、それ以降に作成したキャラクターにのみ反映されます。debug タグの行は開発モード以外ではスキップされます。既存のセーブデータには影響しません。

addMap —— 既存セーブを含む、ロードのたび。 Modパッケージ由来のゾーン行では、このタグがカスタムコンテンツのエントリを登録します。ロードごとにそのゾーンが既に存在するかを確認し、なければ生成して、その行の pos に従って大陸のワールドマップへ刻み込みます。親は次の順で解決されます:

  1. タグ内の値、例:addMap(ntyris) —— 旧CWL構文 addMap_ntyris も受け付けます
  2. parent
  3. ntyris

親はゾーンフルネームで検索されるため、Zone_<id>@<lv> でも素の <id> でも動作し、対象フロアが未生成なら必要に応じて作られます。

WARNING

pos は3つの値を含み、空いているワールドマップのタイルを指している必要があります。pos のないゾーンは -1000,-1000 に置かれ、どのタグを使っても永久に見えず、到達もできません。

複数階層のゾーン

階層モデル

ゾーンは浅いツリーを構成します:world → 大陸 → トップゾーン → その各フロア。lv は地上が 0、地下が負、天空が正です。GetTopZone() は1段しか遡らないため、フロアはトップゾーンの直接の子である必要があります——フロアの中にフロアを入れ子にはできません

既定では、ダンジョンの各フロアは同じシート行を再利用します。フロアの区別はマップファイル名の _F<lv> サフィックスで行われます:

Maps/mymod_dungeon.z        →  lv  0
Maps/mymod_dungeon_F-1.z    →  lv -1
Maps/mymod_dungeon_F-2.z    →  lv -2
Maps/mymod_dungeon_F1.z     →  lv  1   (天空階層)

フルネーム形式でも同様です:Maps/Zone_mymod_dungeon@-1.z

マップファイルのないフロアはランダム生成にフォールバックするので、入口だけ手作りして深層は自動生成に任せることもできます。

階段

TraitStairsDownTraitStairsUp(およびそのサブクラス TraitMineEntranceTraitManhole)は、使用時に行き先を解決します:

  1. 目標階層 = 現在の lv ∓ 1
  2. GetTopZone().FindZone(目標階層) —— 既に存在すればそのフロアを再利用
  3. なければ生成:SpatialGen.Create(GetTopZone().GetNewZoneID(目標階層), トップゾーン, …) として lv を目標階層に設定

既定の GetNewZoneID はゾーン自身のIDを返すため、手順3はすべてのフロアを1行のシートデータにまとめます。特定の深さだけ別のデータ(名前、タイプ、派閥、ボスなど)が必要な場合は、Zone サブクラスでオーバーライドします:

cs
public override string GetNewZoneID(int level)
{
    if (level == -5) return "mymod_dungeon_boss";
    return base.GetNewZoneID(level);
}

戻りの階段は普通は置かなくてよい

両側ともDunGenジェネレーターを使わない場合、階段を使うと進入前イベントがキューされ、行き先フロアの同じ座標にバイオームのスタイルで逆向きの階段が生成されます。そのタイルに既に適切な向きの階段(または TraitStairsLocked)があればスキップされるため、手置きの階段は尊重されます。

同一トップゾーン内を移動する手段は他にも2つあります:

  • TraitElevator —— トップゾーンと既存の全フロアを一覧から選べます。
  • TraitTeleporter —— 同じ刻印IDを持つ他のテレポーターとペアになります。まずマップ内、次にゾーンをまたいで探します。

別のゾーンへ繋ぐ

現在のゾーンのフロアではない場所へ送るには、traitにパラメーターが必要です。Trait.Params は物の trait 列、またはインスタンス単位では c_editorTraitVal から取られます。後者は先頭にカンマが付与されるため、あなたが書く最初の値が GetParam(1) になります:

パラメーター意味
GetParam(1)行き先のゾーンID。テレポート系でないtraitでは、この値が空でなければ外部ゾーンリンクになり、行き先が現在のゾーンの子として生成され isExternalZone が立ちます。
GetParam(2)行き先の階層(lv)。既定は 0
GetParam(3)到着地点の決定に使うテレポートマーカーID。

したがって TraitStairsDown,mymod_funk_house,0 のような専用のThing行を作れば、常にあなたのゾーンへ通じる階段になります。

インスタンスのパラメーターにゲーム内エディタはありません

c_editorTraitValc_idTrait はUnityのInspectorからしか公開されておらず、製品版ではその画面は無効です。公開ビルドでは、パラメーターを trait 列に焼き込んだ専用のThing行を定義するか、スクリプトModからフィールドを直接設定してください。

また TraitNewZone.OnImportMap() はインポート時に c_uidZone をクリアします:マップファイルは、その階段がどの具体的なゾーンインスタンスを指していたかを決して覚えていません。 リンクはtraitパラメーターか階層計算から再導出できる必要があります。

ゾーンプロファイル

idProfileWorld/Zone/Profile/ 配下の ZoneProfile アセットを指し、マップをランダム生成するゾーンでのみ意味を持ちます。空欄の場合はゲームが自動で選びます:lv < 0 なら Undergroundlv > 0 なら Sky、大陸の直下にある地上ゾーンならそのワールドマップタイルに割り当てられたプロファイルです。

組み込みプロファイルには DefaultDungeonDungeonForestDungeonWaterDungeonFactoryDungeonDeadDungeonCursedManorLesimasMineSkyUndergroundU_HillU_PlainU_PlainSmallU_SeasideU_SnowU_Valley、および Random/ 系(Random/R_PlainRandom/R_ForestRandom/R_MountainRandom/R_ShoreRandom/R_SnowRandom/R_WaterRandom/R_Undersea など)があります。これらはUnityリソースなので、Modがシートから追加することはできません。

トラブルシューティング

症状考えられる原因
自作マップではなくランダムマップが読み込まれるidFile がファイル名と一致していない、ファイルが Maps/ 配下にない、またはこのセーブで既にゾーンを訪問済み。
カスタム Zone サブクラスが動かないtype の解決に失敗し、黙って素の Zone にフォールバックしている。綴りと、アセンブリが登録されているかを確認。
ワールドマップに何も出ないpos が空か3値未満、あるいは world から辿れる parentaddMap タグも無い。
ゾーンはあるのに入れないclosed タグが付いている。
インポートしたマップからNPCと家具が消えているエクスポート時に isPlayerCreation が立っていなかった。
ある行以降がまったく読み込まれない途中に id が空の行があり、そこで読み込みが打ち切られた。
階段がどこにも繋がらない行き先を解決できないと「何も起こらない」と表示されます。多くは外部ゾーンリンクの GetParam(1) 欠落です。

This project is an unofficial documentation site and is not affiliated with, endorsed by, or associated with Elin or Lafrontier / Noa. All trademarks are the property of their respective owners.