地图模组编写

***温馨提示：此文章已被多次生草机翻、人工翻译、页面二创、内容重构、多文档多资料缝合、多次洗稿重写以及本人自创内容修改覆盖，请谨慎阅读***
有疑问请留言：Bamboo-nt（留言）

cdda通过“mapgen”在地图被探索时根据随机生成的种子码规律性向大地图内创建建筑物和地形，特定于覆盖贴图地形的功能（按[m]打开map，大地图中你可以看到平铺了的字符组成的大地图）Overmap地形（“oter”）在Overmap\_terrain.json中定义。

默认情况下，oter有一个内置的mapgen函数，该函数与json条目中的“id”匹配（例如：“house”、“bank”等），也可以使用多种功能。当玩家移动到地图上标记为“house”的区域范围内时，游戏会从“house”的功能列表中半随机地选择一个进行运行，放下墙壁，添加物品、怪物、家具等，这一切都是使用mapgen模块内的C++函数在一秒钟内完成的（稍后要记住）。

所有的mapgen都被规定在一个24x24区域（大地图一格）内，即使是类似于电影院、购物中心、医院等大型建筑，亦是如此，它们使用多个“oter\_id”方便向大地图内创建多个24x24区块，并对json\_mapgen中的ASCII字符源码及定义对原有空白区域进行及时覆盖。

为了能在cdda中创建一个随机的或（有点）立体的世界，有许多规则和例外，下面将对此进行说明。

以下有三种方法：

* 添加新的mapgen
* 使用json对象定义
* 使用Update\_mapgen

## 编写mapgen指南

由于mapgen比其它的json文件都要复杂的很多，仅仅熟知其属性只能做到了解，这里翻译了几篇mapgen文献，请在查阅mapgen属性文档前先查阅这个

### 文档中的相关术语

无论是指南还是下面的解析，它们都或多或少了使用了这些术语：

* OMT

overmap向大地图映射图像后的详细建筑地形映射块

* 瓷砖

“格”的错误翻译

* 产卵/繁殖

生草的错误翻译，原译为“生成”

### mapgen基础编写指南

本指南将介绍mapgen的基本知识，您需要编辑哪些文件，每个文件中的标记以及创建特殊或常规城市建筑的区别。有关mapgen条目的完整技术信息，请参阅：mapgen。

首先，让我们介绍一些基本概念以及要添加或编辑的文件。

一旦你习惯了使用CDDA mapgen，它的功能就非常强大。你可以使用很多技巧来增加地图的可变性和趣味性。大多数高级mapgen技术将进入不同的教程。本章介绍了基本概念以及如何创建一个基本的单OMT（overmap映射地形块）大小的建筑。我们将讨论调色板的使用以及如何添加屋顶。

一个特殊的建筑是指在城市外产生的建筑，需要额外的信息才能产生，比如它与城市的距离和有效的OMT地形类型，它们也曾经是游戏中唯一的多层建筑，直到最近的变化允许特殊类型的建筑在城市中诞生，例子有：农场、小屋、LMOE等。

城市建筑的大小可以是单层或多层的，并且其产生地限于城市边界。建筑既可以是城市建筑，也可以是特殊建筑，但这两种类型都需要两组条目。一些汽车旅馆就是这样的例子（参见：2fotel\_city&2fmotel）。

重要政策：自从屋顶项目以来，所有建筑现在都是z层延伸的多层建筑。所有新建筑都应该添加JSON屋顶。很快，所有地下室也将根据底层地图进行定制，因此，如果您想要地下室，最好将专用地下室包括在内。

### 各文件作用

1.您将在data/json/mapgen或其子文件夹中添加一个新的mapgen文件，如果正在为建筑使用现有基础造型，则可以将其附加到该建筑的文件中。

这是建筑的蓝图，它还可以保存建筑的所有数据，以添加家具和战利品（另一种选择请参见调色板）。

2.您将在适当的overmap\_terrain文件（data/json/overmap/overmap\_terrein）中为创建的每个z级别添加条目。

这些条目将定义您的建筑在覆盖图中的外观、其符号、颜色和派生要求，如添加人行道，还将控制一些mapgen函数的标志。

3.您将在specials.json或multitile\_city\_buildings.json中添加条目，具体取决于它是特殊建筑还是城市建筑。

对于multitile\_city\_builds，这将链接建筑的各个z级别和/或多个OMT。

对于特殊情况，这将链接建筑的各个z层或多个OMT，定义任何需要的道路/地铁等，并定义其派生参数。

4.为城市建筑添加regional\_settings.json条目，这将允许它们在世界中被生成。

5.可选，但建议用于任何大型项目：将新的调色板文件添加到mapgen\_palettes文件夹中（您也可以使用任何现有的调色板）。

这是一个文件，可以在保存部分mapgen文件数据的多个地图之间共享。它通常用于定义地形和家具。您还可以将战利品、车辆、怪物繁殖和任何其他数据放入mapgen文件的“object”标签中。

请避免编辑现有的mapgen选项板，因为使用选项板和mapgen文件的组合可能会影响现有的地图。

### 启用mapgen

当我开始一个新的地图项目时，我通常会添加我需要的所有条目，以便它从一开始就在游戏中生成。这样，我可以在工作时测试它，并根据需要进行调整。因此，我建议您在开始项目时设置所有需要的文件。

在开始之前，您需要做出一些决定：

1. 总体规模是多少（有多少个OMT？）
2. 它将生成在哪里
3. 我会使用调色板还是将所有内容都放在mapgen文件中。

* 如果使用调色板，请从一开始就尽可能多地定义它。

4.一些问题：

* 我会用到overmap吗？
* 我想让它连接到地铁或公路吗？
* 我会将mapgen对象数据与调色板结合使用吗（如果您想要两种类型的组合使用中的主类，请参见商场二楼）？

### mapgen地图

这包括mapgen文件映射标志以及它们在外行术语中的作用，您可以从MAPGEN（下面）获取更多信息。

mapgen文件有一些元数据标记和“对象”数据，它们定义了制作地图的所有内容。

#### 元数据

样例：

```
   "type": "mapgen",
   "method": "json",
   "om_terrain": "s_restaurant_coffee",
   "weight": 250,

```

1. “类型”始终是mapgen（我们将在未来的教程中介绍其他映射类型），“方法”始终是JSON。该数据告诉程序如何处理该文件。
2. “om\_terrain”：这基本上是地图的内部名称（而不是显示在覆盖地图上的名称），它通常应该是唯一的，除非您计划使用同一地图的多个变体，它们共享相同的建筑基础形状（注意：我指的是建筑基础的实际形状）。
3. “weight”：此条目是此特定地图与其他共享相同om\_terrain名称的地图的权重。所以，假设你有一个版本的房子，然后你用不同的后代建造一个相同的房子（比如一个家具齐全的房子和一个废弃的房子）。这个权重将决定每一个相对于另一个的产卵频率。假设有家具的房子是100，而被遗弃的房子是20。所以，它将比带家具的房子少5倍。

#### 对象数据

这是定义地图、地形、家具和各种生成类型的标记部分，有几种方法可以放置项目（和嵌套贴图），这些都值得他们自己的指导，对于本文档，我们将使用“显式符号”放置战利品，这是最容易使用的，对象部分中的所有内容都可以放在mapgen\_palette中，但rows和fill\_ter除外。

示例对象段：对象中的所有内容都必须包含在对象的｛｝括号内，否则将不包括在内，如果你放错了端括号，你可能不会出现加载错误。

例子：

```
 "object": {
     "fill_ter": "t_floor",
     "rows": [
       "S___________SSTzzzzzzzTS",
       "S_____,_____SSzMbMbMbMzS",
       "S_____,_____SSSSSSSS/MzS",
       "S_____,_____SSSSSSSS/MzS",
       "S_____,_____SSzzzSSS/MzS",
       "S_____,_____SS|D     <|S",
       "SSSSSSSSSSSSSS|r      OS",
       "SSSSSSSSSSSSSS|r      |S",
       "SVVVVVVVz./Mzz|   #W##|S",
       "SVD>>>>Vz./bMzV   #ww%|S",
       "SV BBB>Vz.b/..{   xwwF|S",
       "SV   B>Vz.Mb..{   flwl|S",
       "SV   B>Vz....zV   flwU|S",
       "SV   B>Vzbbbzz|X  #wwG|S",
       "S|B               |Lwl|S",
       "SO6   6 6 6   B66B|Lwl|S",
       "S|B ^???????^ B66B|Lwl|S",
       "S4SSSSSSSSSSSSSSSSSSSSSS"
     ],
     "terrain": {
       " ": "t_floor",
       "!": "t_linoleum_white",
       "#": "t_linoleum_white",
       "%": "t_linoleum_white",
       "+": "t_door_c",
       ",": "t_pavement_y",
       ".": "t_grass",
       "/": "t_dirt",
       "3": [ "t_door_locked", "t_door_locked_alarm" ],
       ";": "t_linoleum_white",
       "=": "t_linoleum_white",
       "A": "t_linoleum_white",
       "C": "t_linoleum_white",
       "F": "t_linoleum_white",
       "G": "t_linoleum_white",
       "I": "t_door_locked_interior",
       "L": "t_linoleum_white",
       "M": "t_dirt",
       "O": "t_window",
       "S": "t_sidewalk",
       "U": "t_linoleum_white",
       "V": "t_wall_glass",
       "W": "t_fencegate_c",
       "_": "t_pavement",
       "b": "t_dirt",
       "c": "t_linoleum_white",
       "f": "t_linoleum_white",
       "l": "t_linoleum_white",
       "w": "t_linoleum_white",
       "x": "t_console_broken",
       "z": "t_shrub",
       "{": "t_door_glass_c",
       "|": "t_wall_b",
       "<": "t_stairs_up",
       "4": "t_gutter_downspout",
       "T": "t_tree_coffee"
     },
     "furniture": {
       "#": "f_counter",
       "%": "f_trashcan",
       "/": "f_bluebell",
       "6": "f_table",
       "9": "f_rack",
       ">": "f_counter",
       "?": "f_sofa",
       "A": "f_sink",
       "B": "f_chair",
       "C": "f_desk",
       "D": "f_trashcan",
       "F": "f_fridge",
       "G": "f_oven",
       "L": "f_locker",
       "M": "f_dahlia",
       "U": "f_sink",
       "X": "f_rack",
       "^": "f_indoor_plant",
       "b": "f_dandelion",
       "f": "f_glass_fridge",
       "l": "f_rack",
       "r": "f_rack"
     },
     "toilets": { ";": {  } },
     "items": {
       "#": { "item": "coffee_counter", "chance": 10 },
       "6": { "item": "coffee_table", "chance": 35 },
       "9": { "item": "coffee_display_2", "chance": 85, "repeat": [ 1, 8 ] },
       ";": { "item": "coffee_bathroom", "chance": 15 },
       "=": { "item": "coffee_bathroom", "chance": 35 },
       ">": { "item": "coffee_table", "chance": 25 },
       "A": { "item": "coffee_bathroom", "chance": 35 },
       "C": { "item": "office", "chance": 70 },
       "D": { "item": "coffee_trash", "chance": 75 },
       "F": { "item": "coffee_fridge", "chance": 80, "repeat": [ 1, 8 ] },
       "G": { "item": "oven", "chance": 35 },
       "L": { "item": "coffee_locker", "chance": 75 },
       "U": { "item": "coffee_dishes", "chance": 75 },
       "X": { "item": "coffee_newsstand", "chance": 90, "repeat": [ 1, 8 ] },
       "f": { "item": "coffee_freezer", "chance": 85, "repeat": [ 1, 8 ] },
       "l": { "item": "coffee_prep", "chance": 50 },
       "r": { "item": "coffee_condiments", "chance": 80, "repeat": [ 1, 8 ] }
     },
     "monsters": { "!": { "monster": "GROUP_COFFEE_SHOP_ZOMBIE", "chance": 1 } },
     "place_monsters": [ { "monster": "GROUP_ZOMBIE", "x": [ 3, 17 ], "y": [ 13, 18 ], "chance": 1 } ],
     "vehicles": { "c": { "vehicle": "swivel_chair", "chance": 100, "status": 1 } }
   }

```

1. “fill\_ter”：此标记定义家具下使用的默认地形/地板以及行中未定义的符号。通常，选择与之关联的家具最多的地形。
2. “rows”：这是建筑的实际蓝图，标准OMT平铺（覆盖平铺）为24x24平铺，行的x，y坐标从0,0开始，这是地图的左上角。

* 提示：如果你会十字形或熟悉十字绣图案，这应该都很熟悉，你有地图和“图例”区域。

3.“terrain”：这定义了当它们是地形时，行中所有字母的含义。一个符号可以返回一个地形，或者，它可以提供一个从选择的地形中繁殖的机会。以下是一些快速示例：

* “＊”：“t\_door\_c”，：这将使行中的每个“＊”都成为一个关闭的木门。
* “＊”：[[“t\_door\_locked\_epeep”，2]，“t\_doar\_locked\_alarm”，[“t\_door \_locked”，10]，“t\_door\_c”]，：此数组将从一组门中随机选择。有些人被赋予比其他人更高的生成机会，上锁的门最常见，其次是窥视孔门，最终关闭和锁定/报警具有相同的基本重量，并且将产生最少的。
* 注意：在我的示例中，fill\_ter表示floor。因此，如果您有家具要在不同的地板上生成，则必须使用与家具相同的符号，并将其定义为新地板的地形。在上面的例子中，一些家具符号使用白色油毡作为地板，如果你不做这一步，你的家具最终会有错误的地板，如果你砸了它，这会特别明显，我经常在游戏中四处走动时进行最后的地图检查，并在提交地图之前砸家具以检查它们的地形，这可以很好地宣泄情绪。

4.“furniture”标签：和地形一样，这是家具ID及其地图符号的列表，它可以处理与地形相同的阵列。

5.“toilets”和其他特殊定义的家具：你会遇到一些特殊定义的普通家具，这样可以更方便地放置。在我们的示例地图中，条目：“厕所”：{“；”：{}}定义了符号条目，并将自动将水放入厕所。还有一些其他特色家具。

另一个最常见的符号是：“vendingmachines”：｛“D”：｛”item\_group“：”vending\_drink“｝，”V“：｛”item\_ggroup“：”vending\_food“｝｝这为自动售货机分配了两个符号，一个用于食品，另一个用于饮料。注意：您可以将任何itemgroup放入机器中，就像那些子弹头一样。

6.项目产生：有许多方法可以放置项目，本教程仅介绍最简单的显式符号放置，您可以阅读有关战利品繁殖的文档以获取更多信息，请参见下面的ITEM\_SPAWN。

我们的示例使用“items”：作为标记，其他包括：“place\_item”、“place\_items”和“place\_lot”，其中一些允许单独放置项目，另一些允许成组放置，或两者兼而有之，这将在另一个教程中介绍。

现在让我们把这一点分开：

```
   "items": {
     "a": { "item": "stash_wood", "chance": 30, "repeat": [ 2, 5 ] },
     "d": [
       { "item": "SUS_dresser_mens", "chance": 50, "repeat": [ 1, 2 ] },
       { "item": "SUS_dresser_womens", "chance": 50, "repeat": [ 1, 2 ] }
      ]
     }

```

在这种情况下，“a”是其地图中定义的壁炉，所以，我想在壁炉中添加stash\_wooditem\_group，通过在“a”下定义组，我地图中的每个壁炉都会得到这个组，这对于常见的item\_group尤其有用，比如在每个冰箱都会得到相同的item\_ggroup的房子里，机会是它的生成机会，重复意味着它将重复该机会的掷骰2-5次，因此，这个壁炉可以额外储存，或者如果没有掷骰机会，可以有一点或没有。

“d”条目是梳妆台。我想让裁缝从两个可能的项目组中挑选，一个是男士的，另一个是女士的。因此，有一个数组[…]，它包含该符号的所有可能的item\_groups。

您可以向数组中添加任意数量的item\_groups，这是我在通用房屋调色板中的一个机架：

注意：当使用明确的符号放置时，请记住，您的团队有机会在使用该符号的每件家具中进行生成放置，因此最终会非常充足，如果您希望两个书架具有不同的项目生成，请为每个书架指定自己的符号，或者使用其他项目生成格式，例如使用x、y坐标放置的格式。

7.怪物生成：我们的示例列出了两种类型的怪物生成。

```
 "monsters": { "!": { "monster": "GROUP_COFFEE_SHOP_ZOMBIE", "chance": 1 } },
 "place_monsters": [ { "monster": "GROUP_ZOMBIE", "x": [ 3, 17 ], "y": [ 13, 18 ], "chance": 1 } ],

```

第一项是使用显式符号放置技术，结束输入是使用范围x，y坐标来放置怪物，注意：我们不再将怪物放在mapgen文件中，而是使用overmap\_terrain条目，所以只有当您希望特定的怪物组因特定原因而产生时，才使用此选项，有关详细信息，请参见overmap\_terrain部分。

8.载具生成

"vehicles": { "c": { "vehicle": "swivel\_chair", "chance": 100, "status": 1 } }

我们的车辆恰好是一个使用明确符号放置的转椅。

下一个示例使用vehicle\_groups和x、y放置，它还包括轮换和状态，旋转是车辆将在地图上产生的方向，该状态是其整体状态。燃料是非常不言自明的，总是在游戏中测试你的载具，它们的位置可能会很挑剔，而且旋转并不符合你期望的数字，车辆的0,0点可能会有所不同，因此您必须进行实验，以在正确的位置，特别是在狭窄的空间中，获得产卵。

```
   "place_vehicles": [
       { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 12, "y": 18 },
       { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 19, "y": 18 },
       { "chance": 90, "fuel": 0, "rotation": 0, "status": -1, "vehicle": "engine_crane", "x": 28, "y": 3 },
       { "chance": 90, "fuel": 0, "rotation": 90, "status": -1, "vehicle": "handjack", "x": 31, "y": 3 },
       { "chance": 90, "fuel": 30, "rotation": 180, "status": -1, "vehicle": "welding_cart", "x": 34, "y": 3 },
       { "chance": 75, "fuel": 0, "rotation": 180, "status": -1, "vehicle": "junkyard_vehicles", "x": 31, "y": 9 },
       { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 28, "y": 18 },
       { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 35, "y": 18 }
     ]

```

9.家具中的液体：本条目适用于立式储罐。我已将家具条目中的水箱定义为“g”。

```
 "liquids": { "g": { "liquid": "water_clean", "amount": [ 0, 100 ] } },

```

这将在水箱中放置干净的水，并在一定数量范围内生成。

10.当你看更多地图时，你会发现其他一些特殊的放置技巧。我最喜欢的是新种植园主：

由于播种机是一个“密封物品”，您可以定义进入容器的内容。本例将种子（准备收割）放置在播种机中。注意，第一个将放置幼苗，其他的已准备好收割。我给每种播种机类型一个明确的符号，以便更快地放置。

```
 "sealed_item": {
     "1": { "item": { "item": "seed_rose" }, "furniture": "f_planter_seedling" },
     "2": { "item": { "item": "seed_chamomile" }, "furniture": "f_planter_harvest" },
     "3": { "item": { "item": "seed_thyme" }, "furniture": "f_planter_harvest" },
     "4": { "item": { "item": "seed_bee_balm" }, "furniture": "f_planter_harvest" },
     "5": { "item": { "item": "seed_mugwort" }, "furniture": "f_planter_harvest" },
     "6": { "item": { "item": "seed_tomato" }, "furniture": "f_planter_harvest" },
     "7": { "item": { "item": "seed_cucumber" }, "furniture": "f_planter_harvest" },
     "8": { "item": { "item": "soybean_seed" }, "furniture": "f_planter_harvest" },
     "9": { "item": { "item": "seed_zucchini" }, "furniture": "f_planter_harvest" }
   }

```

11.最佳实践：

如果您正在新建房屋，请使用此调色板：“standard\_domestic\_palette”。这些厕所已经分配好了，它涵盖了各种各样的家庭家具。这将使您的房屋与所有其他房屋保持同步，以便进行战利品放置。

所有建筑物也应设置屋顶入口。

虽然json的条目位置并不重要，但尽量保持mapgen文件的顺序，就像大多数现有地图一样。善待未来的贡献者。在文件顶部添加元数据。对象条目排在第二位。在对象条目中，它通常是：调色板、集合点、地形、家具、随机特殊条目，如厕所、物品生成、车辆生成、怪物生成。

所有建筑物都应至少安装一个“t\_gutter\_downpout”用于屋顶通道。玩家至少会喜欢2。如果要为多z层建筑添加排水沟，请不要忘记中间楼层。你需要将落水管错开，以便球员可以爬上去（如梯子）。

如果你把很难爬上去的东西放在屋顶上，一定要通过梯子和楼梯提供更好的屋顶通道。

对于室外的基本草地覆盖，请使用：“t\_region\_groundcover\_uurban”，以保持地图边界的一致性。以下是我的草、灌木和树木的标准植物区系条目：

```
 ".": "t_region_groundcover_urban",
 "A": [ "t_region_shrub", "t_region_shrub_fruit",
 "t_region_shrub_decorative" ],
 "Z": [ [ "t_region_tree_fruit", 2 ], [ "t_region_tree_nut", 2 ],"t_region_tree_shade" ],

```

最后是花卉（家具）：

```
 "p": "f_region_flower"

```

### 设置屋顶

几乎所有的CDDA建筑现在都具备屋顶功能，我们希望保持这种状态。确保提交一份屋顶图和你的建筑。这可以与底层和共享相同建筑形状/基础的任何其他楼层进入同一文件。

所以，与我们刚刚走过的建筑相比，这非常简单。它具有所有相同的基本组件。我建议您首先使用底层地图中的行，并将其转换为“roof\_palette”符号集。基本上，你只需要在排水沟中跟踪轮廓，在下面的t\_gutter\_south旁边添加一个t\_gutter\_drop，然后在上面放置一些基础设施。我在商业建筑屋顶上广泛使用了鸟巢，我们将在高级地图中介绍。

```
 {
   "type": "mapgen",
   "method": "json",
   "om_terrain": "house_01_roof",
   "object": {
     "fill_ter": "t_shingle_flat_roof",
     "rows": [
       "                        ",
       "                        ",
       "                        ",
       "  |222222222222222223   ",
       "  |.................3   ",
       "  |.................3   ",
       "  |.............N...3   ",
       "  5.................3   ",
       "  |.................3   ",
       "  |.................3   ",
       "  |........&........3   ",
       "  |.................3   ",
       "  |......=..........3   ",
       "  |.................3   ",
       "  |----------------53   ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        "
     ],
     "palettes": [ "roof_palette" ],
     "terrain": { ".": "t_shingle_flat_roof" }
   }
 }

```

1. 我总是将\_roof附加到建筑物ID。
2. 查看调色板如何取代我们前面示例中的所有数据。如此干净和简单。
3. 此条目不该有“weight”权重，因为这只会与其建筑一起产生（链接后）。
4. 我的调色板使用“t\_flat\_roof”作为默认屋顶。对于房子，我想要木瓦。因此，我在这个mapgen中添加了“t\_cobble\_flat\_roof”，它将覆盖“.”：“t\_flat\_rooff”的选项板条目。（更多信息请参见高级mapgen）。

在mapgen条目下面有更加详细的屋顶添加教程

该文件位于：data/json/vovermap/multtile\_city\_buildings.json。

### 使用multitile\_city\_buildings.json链接各种mapgen地图

请记住，此维基条目仅适用于城市建筑，不适用于单独的建筑

标准条目：

```
 {
 "type": "city_building",
 "id": "house_dogs",
 "locations": [ "land" ],
 "overmaps": [
   { "point": [ 0, 0, 0 ], "overmap": "house_dogs_north" },
   { "point": [ 0, 0, 1 ], "overmap": "house_dogs_roof_north" },
   { "point": [ 0, 0, -1 ], "overmap": "basement" }
 ]
 },

```

1. “类型”不会改变。它应该始终是“city\_building”。
2. “id”：此id通常与mapgen id相同，但不必相同。我们可以使用更通用的东西，比如“房子”。该ID将用于生成的区域设置中，因此请记住有多少建筑正在使用该ID。我更喜欢不同的ID，因为它使调试生成更加容易。
3. “locations”：定义通过覆盖地形类型可以放置此建筑的位置。默认为土地。
4. “overmaps”：这是您定义地图如何组合在一起的位置，因此让我们将其分解为：｛“point”：[0，0，0]，“overmap”：“house\_dogs\_north”｝，point：它相对于建筑的其他mapgen文件的位置。坐标为[x，y，z]。在本例中，x、y为0，因为每个z级别只有一个贴图。y为零表示这是地面标高。注意，上面的屋顶是1，地下室是-1。
5. 将\_north附加到ID：

* 如果您的建筑旋转，您需要这个罗盘点，以便楼层能够正确匹配。这是通用的地下室mapgen组，因此不会得到\_north（这将随着我们为房屋添加专用楼梯而改变）。

### 使用regional\_map\_settings.json设置覆盖贴图生成

data/json/regional\_map\_settings.json

1. 对于城市建筑和房屋，您将向下滚动到“city”：flag。
2. 找到合适的子标签，通常是“房子”或“商店”。
3. 从multitile\_city\_buildings条目中添加您的ID。这也可以接受mapgen ID，而不抱怨，这就是为什么它们通常是相同的名称。
4. 为您的建筑选择合适的重量。

### 特殊的链接与生成

将条目放入：data/json/vovermap/vovermap\_special/special.json。

这个条目同时完成regional\_map\_settings和multitile\_city\_buildings以及其他有趣的overmap内容。

例子：

```
 {
   "type": "overmap_special",
   "id": "pump_station",
   "overmaps": [
     { "point": [ 0, 0, 0 ], "overmap": "pump_station_1_north" },
     { "point": [ 0, 0, 1 ], "overmap": "pump_station_1_roof_north" },
     { "point": [ 0, 1, 0 ], "overmap": "pump_station_2_north" },
     { "point": [ 0, 1, 1 ], "overmap": "pump_station_2_roof_north" },
     { "point": [ 0, -1, -1 ], "overmap": "pump_station_3_north" },
     { "point": [ 0, 0, -1 ], "overmap": "pump_station_4_north" },
     { "point": [ 0, 1, -1 ], "overmap": "pump_station_5_north" }
   ],
   "connections": [
     { "point": [ 0, -1, 0 ], "terrain": "road", "connection": "local_road", "from": [ 0, 0, 0 ] },
     { "point": [ 1, -1, -1 ], "terrain": "sewer", "connection": "sewer_tunnel", "from": [ 0, -1, -1 ] },
     { "point": [ -1, -1, -1 ], "terrain": "sewer", "connection": "sewer_tunnel", "from": [ 0, -1, -1 ] },
     { "point": [ -1, 1, -1 ], "terrain": "sewer", "connection": "sewer_tunnel", "from": [ 0, 1, -1 ] }
   ],
   "locations": [ "land" ],
   "city_distance": [ 1, 4 ],
   "city_sizes": [ 4, 12 ],
   "occurrences": [ 0, 1 ],
   "flags": [ "CLASSIC" ]
 }

```

1. “type”：是overmap\_special。
2. “id”是覆盖图的建筑id。它也显示在游戏中的过地图上。
3. “过多”的工作方式与城市建筑条目中的工作方式相同。注意，泵站比地面上的1 OMT大，因此y坐标也会发生变化。
4. “connections”：在地图上放置道路、下水道和地铁连接。
5. “locations”：可以放置此建筑的有效OMT类型。
6. “city\_instance”和“city\_size”都是与城市相关的参数。
7. “occurrences”：[0，1]，：Ok，因此，根据是否使用“UNIQUE”标志，occurrence可以表示两种情况。当标志不存在时，这简单地解释为这个特殊可以产生PER过映射的次数。在这种情况下，0比1。如果您使用UNIQUE标志，这将成为一个百分比，因此[1，10]不会是每次覆盖贴图的1到10次，而是在覆盖贴图上产生的几率为1/10。因此，10%的几率在每一次过度映射中产生一次。
8. “flags”：这些标志可用于进一步定义特殊。有关标志列表，请参阅：JSON FLAGS

您可以选择浏览下面的overmap条目以查阅更详细的信息

在以下位置为建筑类型选择文件：data/json/overmap/overmap\_terrain

这组条目定义了建筑在覆盖图上的外观，它支持继承，例子：

```
 {
   "type": "overmap_terrain",
   "id": "s_music",
   "copy-from": "generic_city_building",
   "name": "music store",
   "sym": "m",
   "color": "brown",
   "mondensity": 2,
   "extend": { "flags": [ "SOURCE_LUXURY" ] }
 },
 {
   "type": "overmap_terrain",
   "id": "s_music_roof",
   "copy-from": "generic_city_building",
   "name": "music store roof",
   "sym": "m",
   "color": "brown"
 }

```

每个mapgen ID需要一个条目：

1. “type”将始终是overmap\_terrain。
2. “id”将与您在mapgen文件中使用的id相同。
3. “copy-from”这将从另一个条目复制任何数据，但您在此处定义的除外。
4. “name”名称在覆盖图上的显示方式。
5. “sym”显示在覆盖图上的符号。如果省略，则将使用v<>^
6. “color”符号的颜色
7. “mondesntiy”设置此过贴图平铺的默认怪物密度。您将对一般僵尸生成使用此选项，并为该位置的特殊生成（例如宠物商店的宠物）保留mapgen怪物条目。
8. “扩展”许多这些标志将在未来被NPC用于其AI，尝试添加适合您所在位置的标志，其他人进一步定义了mapgen，比如让人行道生成。

想查看进一步信息请查阅下面的overmap

### 调色板

如前所述，选项板可以保存对象条目包含的几乎所有信息，除了rows和fill\_ter。它们的主要目的是减少向相关地图添加相同基本数据的需要，并保持符号一致性。

添加到mapgen文件对象的条目将覆盖调色板中使用的相同符号。通过这种方式，您可以使用调色板并根据需要对每个mapgen进行选择更改。这对于地毯、混凝土等多种地面地形尤其有用。

当您通过mapgen文件替换地形时，地形效果非常好。我在替代家具方面取得的成功较少，但需要对其进行更多的测试，以明确其何时能按预期工作。我最近注意到，如果您的调色板符号使用值数组，mapgen条目不能覆盖它。

示例：mapgen文件对象的条目：“palette”：[“roof\_palette”]，

调色板元数据：

```
 "type": "palette",
 "id": "roof_palette",

```

其他所有内容看起来都像一系列对象条目，例如roof\_palette：

```
 {
   "type": "palette",
   "id": "roof_palette",
   "terrain": {
     ".": "t_flat_roof",
     " ": "t_open_air",
     "o": "t_glass_roof",
     "_": "t_floor",
     "2": "t_gutter_north",
     "-": "t_gutter_south",
     "3": "t_gutter_east",
     "4": "t_gutter_downspout",
     "|": "t_gutter_west",
     "5": "t_gutter_drop",
     "#": "t_grate",
     "&": "t_null",
     ":": "t_null",
     "X": "t_null",
     "=": "t_null",
     "A": "t_null",
     "b": "t_null",
     "c": "t_null",
     "t": "t_null",
     "r": "t_null",
     "L": "t_null",
     "C": "t_null",
     "Y": "t_null",
     "y": "t_null"
   },
   "furniture": {
     "&": "f_roof_turbine_vent",
     "N": "f_TV_antenna",
     ":": "f_cellphone_booster",
     "X": "f_small_satelitte_dish",
     "~": "f_chimney",
     "=": "f_vent_pipe",
     "A": "f_air_conditioner",
     "b": "f_bench",
     "c": "f_counter",
     "t": "f_table",
     "r": "f_rack",
     "L": "f_locker",
     "C": [ "f_crate_c", "f_cardboard_box" ],
     "Y": "f_stool",
     "s": "f_sofa",
     "S": "f_sink",
     "e": "f_oven",
     "F": "f_fridge",
     "y": [ "f_indoor_plant_y", "f_indoor_plant" ]
   },
   "toilets": { "T": {  } }
 }

```

如果您想查看更复杂的调色板，data/json/mapgen\_palettes/home\_general\_palette.json中的standard\_domestic\_palette是一个设计用于所有CDDA房屋的调色板。它包括战利品的产生，并占到了房屋中使用的大部分家具。我还留下了一个符号列表，可以在mapgen文件中用于特定位置的需要。

最后，位于data/json/mapgen\_palettes/home\_w\_palette.json的一系列house\_w调色板被设计用于使用嵌套mapgen的房屋。有一个调色板专门用于基础，另一个用于巢穴，最后还有一个我为家庭户外嵌套块设计的调色板。

最终意见：

这里的信息应该足以让您绕过mapgen并开始制作地图，但有很多变化将在重点介绍中介绍。

本文件未涵盖：

* 嵌套贴图及其位置
* NPC生成
* 复杂地板选项的高级地形技巧
* 你和陷阱、地形
* update\_mapgen（NPC和玩家触发的地图更新）
* 派系阵营扩展图
* 领域内生成家具

## 进阶mapgen指南

本指南假设您熟悉基本mapgen元素和添加常规mapgen。它是对mapgen.md和overmap.md文档的补充。

本指南将包括：

* 何时使用嵌套mapgen与常规mapgen变体。
* 如何创建和生成嵌套贴图。
* 一些嵌套映射的可能性。
* NPC生成。
* 利用现有的嵌套映射进行建模。
* 使用陷阱的基本update\_mapgen。
* 大型建筑的合并地图。

您将使用的文件：

一个新的或现有的文件来保存嵌套的地图条目（mapgen中有一个子文件夹用于嵌套的地图文件）。
你想要你的巢在其中产生的mapgen文件
调色板（可选）

初学者教程中使用的文件（mapgen文件、overmap\_terrain和specials.json或multitile\_city\_building.json/regional\_map\_settings.json。）

### 嵌套贴图与变体贴图

变量映射是mapgen文件，通过使用相同的om\_terrain名称并对每个变量应用权重条目以生成彼此相关的映射，可以完全替换另一个映射变量。

嵌套贴图是应用于现有mapgen文件的新贴图层。它们可以覆盖现有的地形、家具、添加战利品、怪物、车辆等。它们可以包含常规地图生成器在对象条目中包含的任何内容。嵌套贴图是通过向主mapgen的对象条目中添加条目而生成的。它们可以是从单个平铺到整个24x24重叠地形的任何大小。
这两种方法都为增加地图的多样性提供了优点和缺点。

变体适用于大型结构变更或全面检修。

例如，我可以在一个有谷仓的农场中做一部分，而在另一个农场中做一些农田。

如果我希望整个地图有明显不同的变体，比如同一栋房子是空的、废弃的、有家具的。

在我们将json屋顶（和其他链接的z级别）添加到mapgen之前，大多数建筑都使用了变体来生成，大多数已经被重命名，但一些变体仍然存在，特别是在较旧的特色中。

嵌套贴图有助于为贴图添加更具针对性的多样性和随机性。除了变体提供的功能外，嵌套映射还可以让您执行以下操作：

重新布置房间中的家具，或根据具体情况重新布置每个房间的家具。

添加较小的有针对性的主题内容，如布景、额外的怪物、隐藏的房间、罕见的产卵。

拥有不同的战利品和房间主题集，可在多个建筑中随机生成。

### update\_mapgen（\_M）

update\_mapgen在游戏期间触发，而不是在worldgen期间初始化。我将在本文档中介绍update\_mapgen的一些用法，但它应该有自己的指南。

陷阱可以触发地图生成更改。

允许任务触发mapgen更改。

由派系营地建筑系统用于蓝图和嵌套地图。

由map\_extras使用。

更新mapgen映射类似于嵌套映射，但应用于现有映射，而不是mapgen文件。与嵌套地图一样，它们可以覆盖现有地形、家具、为战利品、怪物、车辆等添加繁殖。它们可以包含常规地图生成器在对象条目中包含的任何内容。它们可以是从单个平铺到整个24x24覆盖贴图地形的任何大小，甚至可以包括嵌套的mapgen对象。

### 合并的地图

合并映射是指将多个OMT的mapgen条目合并为单个mapgen条目。这些行组合成一组地图。这通常用于提高json的可读性和更紧凑的文件大小。它们通常与单个OMT mapgen处理相同，但本文档中包含一些例外情况。与任何mapgen选项一样，也存在权衡，一个显著的限制是多个OMT的单个fill\_ter条目。

创建嵌套贴图：

在添加嵌套贴图之前，您需要进行一些选择。

* 它们的目的，它们在哪里生成，多个地点？
* 如果是在更大的建筑内，你会包括门/墙吗？
* 你需要制作多大尺寸的地图。
* 嵌套地图使您能够覆盖或填充现有地图生成器的一部分。嵌套映射条目的内容可以包含mapgen对象中的任何条目（fill\_ter除外）。这包括在嵌套映射中添加嵌套映射以获得额外的可变性。

嵌套映射的示例json条目：

```
 {
   "type": "mapgen",
   "method": "json",
   "nested_mapgen_id": "room_9x9_recroom_E",
   "//": "an entertainment area for various recreations",
   "object": {
     "mapgensize": [ 9, 9 ],
     "rotation": [ 0, 3 ],
     "rows": [
       "|HHH...=|",
       "|Hl....x|",
       "|%.....=|",
       "|.A.A..&|",
       "|JJ5JJ  +",
       "|       |",
       "|mVJ14 T|",
     ],
     "palettes": [ "standard_domestic_palette" ],
     "terrain": {
       ".": "t_carpet_green",
       "H": "t_carpet_green",
       "l": "t_carpet_green",
       "A": "t_carpet_green",
       "=": "t_carpet_green",
       "x": "t_carpet_green",
       "%": "t_carpet_green",
       "&": "t_carpet_green"
     },
     "furniture": { "%": "f_arcade_machine", "=": "f_speaker_cabinet", "&": "f_pinball_machine" },
     "place_loot": [ { "item": "stereo", "x": 7, "y": 2, "chance": 100 }, { "item": "laptop", "x": 5, "y": 5, "chance": 60 } ]
   }
 }

```

这应该很熟悉，因为它看起来像mapgen中的对象条目，并且共享相同的类型，注意，ID现在是nested\_mapgen\_ID，对象使用新条目mapgensize

* nested\_mapgen\_id：您的id应该提供有关嵌套的有用信息。多个嵌套可以共享同一ID。
* weight：这个值是新的，大多数嵌套贴图还没有。它允许您对共享相同nested\_mapgen\_id（也称为嵌套的变体）的嵌套的后代进行加权。
* mapgenize：嵌套的mapgen可以是1x1到24x24的任何大小，但必须是方形。您不必使用行条目的每一行或每一列。任何未使用的部分都将返回到主mapgen。
* 地形和家具：如果没有fill\_ter，您需要定义家具下的每个楼层地形。如果不这样做，它将返回到主mapgen的fill\_ter。在上面的例子中，1/2的地图上有一块绿色地毯，其余的人则在地图（室内混凝土）的地板上。如果需要覆盖主mapgen中的现有家具，可以使用t\_null和f\_null的组合来覆盖先前存在的mapgen。

小贴士：如果你在做室内空间，请注意门的位置和通道。
对于有墙的嵌套，我通常把门放在墙的中央。
对于开放式平面图嵌套，我尝试在常规mapgen中保留门的角落空间（如果我可以设计带有嵌套的mapgen）。

示例：请注意，角瓷砖都是空的。

```
     "rows": [
       " CR ",
       "O   ",
       " EE ",
       " EE "
     ],

```

带有可能的门位置的房间轮廓示例。表示上述嵌套的任何有效门位置。这种方法为您提供了在不堵塞门口的情况下将此嵌套安装到封闭房间的最大可能性。我把一些室内植物或其他小家具扔到主地图中未使用的角落里，填满房间。

将嵌套装配到现有基础/建筑轮廓中可能有点麻烦，尤其是当您添加共享相同ID或在许多地图上使用的变体时。因此，在所有巢穴的可预测位置设置门将有助于它们在未来地图中的重复使用。

我们使用一个命名约定，其中包括嵌套的映射大小和一些方向指示，或者在json条目中添加一个带有额外上下文的注释。

某些ID：

* room\_9x9\_recroom\_N
* room\_9x9\_recroom\_S
* 7x7\_band\_practise\_open

通过使用房间和指南针的方向，它可以快速地将巢识别为具有墙/门和门的方向。乐队练习室是一个开放空间，不包括墙壁。包括地图大小将使搜索、调试生成和重新使用嵌套变得更容易。

### 调试测试

这么多的嵌套，很难找到可以使用的！

我们最近已经通过游戏中的调试获得了生成嵌套地图的能力，这对于确保嵌套适合、不与现有地图中的元素冲突、定向良好而无需调整生成权重来强制嵌套自然生成是一个巨大的帮助。
这也是一个很好的方法来“货比三家”现有的巢穴，以便在地图中重复使用。
要在游戏中调试生成嵌套贴图，请执行以下操作：

* 打开调试菜单（您需要添加密钥绑定）
* 选择贴图[m]
* 选择派生嵌套映射[n]
* 使用[/]搜索列表
* 使用选择器放置嵌套贴图。指示器是嵌套的0,0坐标。

您很快就会明白为什么使用连贯的名称格式很好。

### 迷你嵌套

嵌套可以小到一个瓦片，如果你想为物品、怪物、车辆、NPC或其他元素生成特殊或稀有的嵌套，这非常有用。

一个特定战利品群产卵的例子：这些巢穴用于地下室研究中的一个更大的巢穴。我不想让这间书房同时提供所有魔法课的书籍。我为每个法术类item\_group制作了嵌套：

3 1x1嵌套地图，仅包含战利品放置。它们进了一个更大的窝。

### NPC生成

如果你在主地图生成器上使用place\_npc，npc将100%的时间产生。NPC就像难民中心的人被安置成这样。

然而，许多NPC应该更接近随机遭遇。下面的示例创建了一个生成NPC（并且仅生成NPC）的嵌套：

```
 {
   "type": "mapgen",
   "method": "json",
   "nested_mapgen_id": "SEER_Brigitte_LaCroix_spawn",
   "object": { "mapgensize": [ 1, 1 ], "place_npcs": [ { "class": "SEER_Brigitte_LaCroix", "x": 0, "y": 0 } ] }
 }

```

你也可以自定义NPC产生的环境。对于在一家餐厅中生成的厨师NPC，他们会获得以幸存者为主题的设置：注意在地图的大部分区域使用了t\_null。许多地图未使用，依赖于主地图生成器。它重新布置了家具以封锁入口，并增加了一点幸存者的窝点的味道。

```
 {
   "type": "mapgen",
   "method": "json",
   "nested_mapgen_id": "chef_s_restaurant",
   "object": {
     "mapgensize": [ 13, 13 ],
     "rows": [
       "mt_________#t",
       "____________r",
       "__________ffr",
       "___________W_",
       "_____________",
       "_____________",
       "_____________",
       "_____________",
       "_____________",
       "_____________",
       "_____________",
       "_____________",
       "_____________"
     ],
     "terrain": { "_": "t_null", "-": "t_wall", "W": "t_window_boarded" },
     "furniture": { "r": "f_rack", "f": "f_fridge", "t": "f_table", "#": "f_counter", "m": "f_makeshift_bed" },
     "place_npcs": [ { "class": "survivor_chef", "x": 5, "y": 1 } ],
     "place_loot": [
       { "group": "produce", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "groce_meat", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "groce_dairyegg", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "bar_food", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "bar_fridge", "x": [ 10, 11 ], "y": 2, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "jackets", "x": 0, "y": 0, "chance": 70, "repeat": [ 2, 3 ] },
       { "group": "alcohol_bottled_canned", "x": 1, "y": 0, "chance": 80 },
       { "group": "baked_goods", "x": [ 2, 4 ], "y": 2, "chance": 50, "repeat": [ 2, 3 ] },
       { "group": "groce_bread", "x": [ 2, 4 ], "y": 2, "chance": 50, "repeat": [ 2, 3 ] },
       { "group": "cannedfood", "x": [ 5, 6 ], "y": 0, "chance": 50, "repeat": [ 2, 3 ] },
       { "group": "cannedfood", "x": [ 9, 11 ], "y": 0, "chance": 50, "repeat": [ 2, 3 ] }
     ]
   }
 }

```

### 生成嵌套地图

您可以使用显式符号放置或x，y坐标，在通常的两种方法中生成嵌套。我遇到过一些罕见的情况，其中一种风格有效，另一种风格无效，但尚未确定原因。

### x,y坐标放置

如果你想让嵌套的生成位置在地图上移动一点，这就增加了一些不错的可变性。我在屋顶上广泛使用了这种方法，因为它们是开放空间，我想减少它们在其他情况下的静态。

在主mapgen的对象中，输入以下条目：

```
   "place_nested": [
       {
         "chunks": [ [ "null", 30 ], [ "roof_6x6_utility", 30 ], [ "roof_4x4_utility_1", 40 ] ],
         "x": [ 5, 14 ],
         "y": [ 14, 16 ]
       }
     ]

```

一个NPC样例：

```
 "place_nested": [ { "chunks": [ [ "SEER_Brigitte_LaCroix_spawn", 20 ], [ "null", 80 ] ], "x": 18, "y": 6 } ]

```

这些块是嵌套的nested\_mapgen\_id，每个块都包括它们彼此之间的产卵权重。添加空条目允许嵌套有机会不生成任何内容。空值也可以确保你的NPC相关巢穴有机会产生，而不是被保证。

### 显式符号放置

在主mapgen的对象中，添加以下条目：在主mapgen's行中，无论我在哪里放置1，第一组块都将生成。另一组将在我放置2的地方产生。应将符号放置在嵌套贴图的0,0坐标的任何位置。

```
   "nested": {
       "1": {
         "chunks": [ [ "null", 60 ], [ "room_10x10_woodworker_E", 30 ], [ "room_10x10_guns_E", 10 ], [ "room_10x10_guns_N", 10 ] ]
       },
       "2": {
         "chunks": [
           [ "null", 50 ],
           [ "room_6x6_brewer_N", 10 ],
           [ "room_6x6_junk", 30 ],
           [ "room_6x6_office_N", 30 ],
           [ "6x6_sewing_open", 20 ],
           [ "6x6_electronics_open", 10 ],
           [ "room_6x6_brewer_W", 10 ],
           [ "room_6x6_junk_W", 30 ],
           [ "room_6x6_office_W", 30 ]
         ]
       }
     }

```

带有符号的主mapgen行：

```
    "rows": [
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "        |.g...JJJWZ.U|  ",
       "        |F..........<|  ",
       "        |............|  ",
       "        |............|  ",
       "        |......2.....|  ",
       "  |1.................|  ",
       "  |..................|  ",
       "  |..................|  ",
       "  |..................|  ",
       "  |..........|          ",
       "  |..........|          ",
       "  |..........|          ",
       "  |..........|          ",
       "  |..........|          ",
       "                        ",
       "                        "
     ],

```

### 嵌套贴图和z级别

目前，嵌套贴图不支持z级链接，因此您创建的任何嵌套贴图都将依赖于主mapgen的屋顶或尝试生成c++屋顶。这项工作取得了不同程度的成功。大多数情况下，当我不能在温室里安装玻璃屋顶时，我觉得很烦人。

利用现有的嵌套映射进行建模。

随着vanilla中使用的嵌套地图的增加，建模者可以利用这些现有条目将其模型地图合并到现有建筑中。这将大大扩展mod将其内容添加到普通地图中的能力。通过使用相同的嵌套mapgen-id并为新嵌套和现有嵌套指定权重（根据需要）。

我建议改装者看看现有的地图，看看是否有一个符合他们想要的改装巢穴的整体尺寸、方位和产卵稀有度。您可以在github中搜索嵌套的mapgen id，以确保其表示满足您的需求。

### update\_mapgen（\_M）

如前所述，由于游戏过程中发生的事件，Update\_mapgen将应用于现有地图。

更新mapgen将在高级指南中进行更多介绍，以解决其在派系基地和NPC任务中的用途。

对于本指南，最有可能使用陷阱触发的update\_mapgen。这是一个非常新的功能，目前在microlab和magiclysm mod的魔法地下室中使用。

由于它仍然是一个新功能，所以没有进行太多扩展。目前适用以下限制：
陷阱只能由玩家或NPC移动到陷阱瓦片触发。

我们将在micro\_lab上使用Magiclysm地下室中发现的更简单的实现，但我也建议查看microlab的多陷阱系统。

您需要一个陷阱条目（或使用现有的）

陷阱示例：

```
 {
   "type": "trap",
   "id": "tr_magic_door",
   "name": "magic door",
   "color": "brown",
   "symbol": "+",
   "visibility": 99,
   "avoidance": 99,
   "difficulty": 99,
   "action": "map_regen",
   "map_regen": "magic_door_appear",
   "benign": false
 }

```

所有特定于陷阱的条目都可以在其他文档中了解。这里我们关注的是action和map\_regen条目。我们希望此陷阱触发map\_regen操作，并且map\_regen引用我们的update\_mapgen\_id。

update\_magen与嵌套贴图的相似性：

它可以针对较小的地图块。

它使用对象数据。

### 与嵌套贴图的区别

使用的坐标是指它正在更新的主地图。

update\_mapgen示例：

```
 {
 "type": "mapgen",
 "update_mapgen_id": "magic_door_appear",
 "method": "json",
 "object": {
   "place_terrain": [ { "ter": "t_carpet_green", "x": 12, "y": 6 } ],
   "place_furniture": [ { "furn": "f_beaded_door", "x": 12, "y": 6 } ]
 }
 }

```

在本例中，我使用了一个包含place\_terrain和place\_furniture的精简替代方案，而不是创建行和分配符号。x，y坐标是指正在改变的主地图。这也可以使用我们通常在mapgen中使用的典型行编码。

主要的mapgen和放置你的陷阱：

```
 {
   "type": "mapgen",
   "method": "json",
   "om_terrain": [ "magic_basement" ],
   "weight": 100,
   "object": {
     "fill_ter": "t_carpet_green",
     "rows": [
       "                        ",
       "        |gUU|yRRRRRRET| ",
       " |&.........|.yrrr...<| ",
       "        |/.....H..x| ",
       "        |B~~|.....s..x| ",
       "        |BYt|RRRR.....| ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        "
     ],
     "palettes": [ "standard_domestic_palette" ],
     "place_traps": [ { "trap": "tr_magic_door", "x": 21, "y": 4 } ]
   }
   }

```

我已经把陷阱放在衣架下面，以防止意外触发。注意：当触发时，陷阱将更新房间对面的墙，并带有珠状门入口。

### 合并的地图

合并后的映射是json，它将多个OMT组合在一个mapgen条目中。没有大小限制，但您应该尽最大努力保持json可读，因此将其分成可管理的段。3个OMT从左到右加起来是72个平铺，很容易符合CDDA的偏好，即每行不超过100列，但有些人可以加起来多达5个OMT。在较小的屏幕上，从左到右共有5个以上的OMT很难阅读，应避免。同样的逻辑也适用于垂直分组：2-3个OMT很容易在大多数屏幕上显示，但更多的内容很难阅读。

您可以将现有的OMT插入到合并的地图中，包括森林、田野、沼泽和水瓦片。像森林这样的通用瓦片不需要添加到mapgen文件中，它们将在specials.json或multitile\_city\_buildings条目中调用。

在大多数情况下，合并的地图使用与常规mapgen文件完全相同的规则和条目，但有几个明显的例外：
om\_terrain值：此示例适用于覆盖贴图上4个OMT宽、3个OMT长（4x3）的贴图。OMT的每一行都被分组到一个数组中。

```
 "om_terrain": [
     [ "farm_stills_4", "farm_stills_3", "farm_stills_2", "farm_stills_1" ],
     [ "farm_stills_8", "farm_stills_7", "farm_stills_6", "farm_stills_5" ],
     [ "farm_stills_12", "farm_stills_11", "farm_stills_10", "farm_stills_9" ]
   ]

```

每个OMT的坐标将延续行和列编号，它们不会在每个地图边界重置为0,0。

对于我们的农场，坐标为：

* x sets:

* + first OMT: 0,23
	+ second OMT: 24,47
	+ third OMT: 48,71
	+ fourth OMT: 72,95

* y sets:

* + first row: 0,23
	+ second row: 24,47
	+ third row: 48,71

对象条目行一起反映所有OMT，所有其他对象条目在所有OMT中共享：

```
   "rows": [
       " IFFFFFFFI,,,,IFFFFFFFIffffffffffffffff ,,,, ffffIFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFI ",
       " F        ,,,,        F   ????  ????   P,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,        ,           F ",
       " F $$$$$$$,,,,$$$$$$$ F   -ww-  -ww-    ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F ---..----..---  ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,   ,                F ",
       " F        ,,,,        F -x..........x-   ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ F -....hhhh....w   ?,?     I                    ,,,,                    F ",
       " F        ,,,,        F w....tttt....-????,?     F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD,F ",
       " F        ,,,,        F w....tttt....+,,,,,?     F     ,           Q  ,,,,    ,          ,    F ",
       " F $$$$$$$,,,,$$$$$$$ F w....tttt...Y-??????     F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F -....hhhh....w           F,                   ,,,,           ,        F ",
       " F        ,,,,        F -x..........x-   -ww-    F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ F ----......--------HH---- F           ,        ,,,,                    F ",
       " F        ,,,,        F -......................- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,Q       F w.;;;;;;;;;;;;;;;;;;;;.w F                    ,,,,       ,        Q   F ",
       " F $$$$$$$,,,,$$$$$$$ F -.....................x- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F ---+-----+-----+-----+-- F     ,        ,     ,,,,                  , F ",
       " F        ,,,,        F -iiiiu-H...-BB...kk-TiS- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ F -Siiiu-t...-.....h.-iii- F    ,               ,,,,            ,       F ",
       " F        ,,,,        F woiiiu-H...-BB.....-iii- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F -eiiiu-.BB.-.....h.-bbb- F                    ,,,,    ,               F ",
       " F $$$$$$$,,,,$$$$$$$ F -iiiiu-.BBd-BBdddkk-bbb- F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F ---+----ww----ww-------- F,              ,    ,,,,                   ,F ",
       " F        ,,,,        F    ,                     F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ Iffff,fffffffffffffffffffffI        ,           ,,,,      ,             F ",
       " F        ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,   ,        Q       F ",
       " F $$$$$$$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,           ,        F ",
       " F        ,,,,        I          ,,     ,,,,,O   I DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ F #==#==#  ,,   ##MMMMM##  F         Q          ,,,,    ,              ,F ",
       " F        ,,,,        F #L_q__#  ,, ? #E_____O#  F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F #L_q__# ,,,   #E______#  F                    ,,,,                    F ",
       " F $$$$$$$,,,,$$$$$$$ F #L____# ,,   &#E______W  F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F #L_c__# ,,,,,,+_______#  F       ,            ,,,,          ,         F ",
       " F        ,,,,        F ####### ,,   ?#l______#  F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ F  ?      ,,    #l______W  F,             ,     ,,,,                    F ",
       " F        ,,,,        F         ,,,   #l______#  F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F     ?    ,,   #_______#  F     ,              ,,,,   ,        ,       F ",
       " F $$$$$$$,,,,$$$$$$$ F ?        ,,?  #########  F DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        F          ,,              F         ,          ,,,,                    F ",
       " F        ,,,,        IFFFFFFFFFI,,IFFFFFFFFFFFFFI DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F $$$$$$$,,,,$$$$$$$ f       ?  ,,     ?        f    ,           ,   ,,,,       ,            F ",
       " F  Q     ,,,,        f  7   7   7,,  7   7   7  f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        f ?       ? ,,        ?    f         ,          ,,,,                    F ",
       " F $$$$$$$,,,,$$$$$$$ f  ,,,,,,,,,,,,,,,,,,,,,,  f DDDDDDDDDDDDDDDDDDD,,,,DDDDDDDDDDDDDDDDDDD F ",
       " F        ,,,,        f           ,,             f           ,        ,,,,           Q        F ",
       " F        ,,,

```

（太大了，别复制了）

……

总之后面只是以“]”为结尾，剩下的没有

关于生成物品、车辆和怪物的重要注意事项：

虽然这些地图是为了可读性而合并的，但我们的mapgen进程不会自动识别这些地图。使用x，y坐标添加繁殖时，不能跨越OMT边界。如果您希望这些繁殖在多个OMT中发生，请创建多个条目。这适用于x和y坐标。

例如：每个x坐标包含一个来自商场某一部分的OMT。

```
   "place_monsters": [
       { "monster": "GROUP_MALL", "x": [ 2, 23 ], "y": [ 2, 23 ], "density": 0.15 },
       { "monster": "GROUP_MALL", "x": [ 26, 47 ], "y": [ 2, 23 ], "density": 0.3 },
       { "monster": "GROUP_MALL", "x": [ 49, 71 ], "y": [ 2, 10 ], "density": 0.2 },
       { "monster": "GROUP_MALL", "x": [ 56, 68 ], "y": [ 17, 21 ], "density": 0.1 },
       { "monster": "GROUP_MALL", "x": [ 73, 95 ], "y": [ 2, 10 ], "density": 0.2 },
       { "monster": "GROUP_MALL", "x": [ 73, 95 ], "y": [ 17, 19 ], "density": 0.1 },
       { "monster": "GROUP_MALL", "x": [ 98, 119 ], "y": [ 0, 11 ], "density": 0.2 },
       { "monster": "GROUP_MALL", "x": [ 96, 105 ], "y": [ 16, 21 ], "density": 0.1 },
       { "monster": "GROUP_MALL", "x": [ 170, 191 ], "y": [ 2, 23 ], "density": 0.1 },
       { "monster": "GROUP_MALL", "x": [ 194, 215 ], "y": [ 2, 23 ], "density": 0.05 }
     ]

```

* 您可以通过使用显式符号放置来解决这个问题，这将适用于行中的所有OMT。这可能会让怪物和车辆生成变得有点混乱，所以我通常将它们保持在x，y坐标。

* 在2个OMT上生成的车辆根本不会生成。所以，如果你不能让你的车辆生成，调整它的位置。车辆的0,0坐标可以根据车辆自己的json条目而变化，因此这通常需要一些尝试和错误才能使它们很好地生成。

* 所有类型的嵌套地图都可以在合并地图中使用，但它们不能跨越边界线（嵌套地图将在边界处截断）。

* 有关怪物产卵的更多信息，请参见MAPGEN

注意：设置点类型条目（见下面的示例）在合并的映射中不太适用，并且已经报告了该问题。如果使用此条目，则合并地图中的每个OMT中都会重复这些点。

样式：

```
   "set": [
       { "point": "trap", "id": "tr_funnel", "x": [ 2, 9 ], "y": 19, "repeat": [ 1, 2 ] },
       { "point": "trap", "id": "tr_cot", "x": [ 2, 9 ], "y": [ 15, 17 ], "repeat": [ 1, 2 ] }
     ]

```

我想把这个床和漏斗放在第一个OMT中，但每次遇到新的OMT边界时都会重复。

## 添加json屋顶

将json屋顶添加到建筑中需要在mapgen过程中使用更多的文件将屋顶和建筑链接在一起。

将要编辑的文件有：

* data/json/mapgen/[建筑名称].json：建筑和屋顶的地图。
* data/json/overmap\_terrain.json：定义建筑的overmap特性。
* data/json/reregional\_map\_settings.json：定义建筑的overmap生成设置。
* data/json/overmap/multitile\_city\_buildings.json：将构建层链接在一起。

### 制作屋顶地图

如果您是地图创建新手，请参阅MAPGEN条目以创建地图。
打开包含建筑数据地图的文件/json/mapgen/[建筑名称].json为屋顶添加一个新条目。可以复制建筑条目，因为屋顶需要相同的基础迹线。
给屋顶一个唯一的om\_terrain ID。下面是主楼层和屋顶om\_terrain ID的示例

```
 "om_terrain": "abstorefront",
 "om_terrain": "abstorefront_roof",

```

注意：如果要将屋顶添加到与其他地图共享公共om\_terrain ID的现有建筑中，则需要将现有楼层的om\_terrainID更改为唯一。
保持墙的轮廓与原始楼层不同，在建筑外部添加t\_open\_air，并在建筑的迹线上添加t\_flat\_roof。terrain.json中有一些平顶地形可供选择。

屋顶有许多地形和家具结构，包括排水沟、烟囱和屋顶涡轮机通风口。浏览json/terrain-roofs.json和furniture-roof.json以获取想法。考虑屋顶通道，可以使用梯子、楼梯和排水沟。有些家具也是可以攀爬的。

如果您想合并data/json/mapgen/nested\_clouds\_roof.json中有一组可选的嵌套映射块。在此处也为屋顶添加任何新的嵌套块。
屋顶入口示例：

```
 {
   "type": "mapgen",
   "method": "json",
   "om_terrain": "abstorefront_roof",
   "object": {
     "fill_ter": "t_flat_roof",
     "rows": [
       "                        ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -....................- ",
       " -......&.............- ",
       " -....................- ",
       " -.................>..- ",
       " --5------------------- ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        ",
       "                        "
     ],
     "palettes": [ "roof_palette" ],
     "place_items": [ { "item": "roof_trash", "x": [ 2, 21 ], "y": [ 3, 14 ], "chance": 50, "repeat": [ 1, 3 ] } ],
     "place_nested": [
       {
         "chunks": [ [ "null", 20 ], [ "roof_4x4_party", 15 ], [ "roof_4x4_holdout", 5 ], [ "roof_4x4_utility", 40 ] ],
         "x": [ 3, 15 ],
         "y": [ 3, 7 ]
       }
     ]
   }
 }

```

### 连接主楼层和屋顶

导航到json/overmap/multittile\_city\_buildings.json，查找每个在z坐标轴以上占用一个overmap瓦片的建筑（学校、豪宅）。为主楼层添加一个入口。点坐标定义为建筑物的x、y、z位置。1将屋顶放置在一楼上方一个z标高处。向北附加旋转建筑，以确定z轴标高的方向。

```
 {
   "type": "city_building",
   "id": "abstorefront",
   "locations": [ "land" ],
   "overmaps": [
     { "point": [ 0, 0, 0 ], "overmap": "abstorefront_north" },
     { "point": [ 0, 0, 1 ], "overmap": "abstorefront_roof_north" }
   ]
 }

```

### 特殊overmap

特殊Overmap的处理方式略有不同。它们使用json/overmap/overmap\_special/specials.json来链接z级别和生成overmap。特辑不需要data/json/regional\_map\_settings.json中的条目

例子：

```
 {
   "type": "overmap_special",
   "id": "Evac Shelter",
   "overmaps": [
     { "point": [ 0, 0, 0 ], "overmap": "shelter_north" },
     { "point": [ 0, 0, -1 ], "overmap": "shelter_under_north" },
     { "point": [ 0, 0, 1 ], "overmap": "shelter_roof_north" }
   ],
   "connections": [ { "point": [ 0, -1, 0 ], "terrain": "road", "connection": "local_road", "from": [ 0, 0, 0 ] } ],
   "locations": [ "wilderness" ],
   "city_distance": [ 3, 10 ],
   "city_sizes": [ 4, -1 ],
   "occurrences": [ 0, 2 ],
   "flags": [ "CLASSIC", "URBAN" ]
 }

```

### 添加overmap\_terrain条目

导航到data/json/overmap\_terrain/每个z级别都会获得一个条目，该条目定义了它在overmap上的显示方式。名称字段将决定游戏中overmap中显示的内容。条目应共享相同的颜色和符号。

```
 {
   "type": "overmap_terrain",
   "id": [ "abandonedwarehouse", "abandonedwarehouse_1", "abandonedwarehouse_2", "abandonedwarehouse_3", "abandonedwarehouse_4" ],
   "copy-from": "generic_city_building",
   "name": "abandoned warehouse",
   "sym": "w",
   "color": "brown"
 },
 {
   "type": "overmap_terrain",
   "id": [
     "abandonedwarehouse_roof",
     "abandonedwarehouse_1_roof",
     "abandonedwarehouse_2_roof",
     "abandonedwarehouse_3_roof",
     "abandonedwarehouse_4_roof"
   ],
   "copy-from": "generic_city_building",
   "name": "abandoned warehouse roof",
   "sym": "w",
   "color": "brown"
 }

```

### 添加到regional\_map\_settings

导航到data/json/reregional\_map\_settings.json

这决定了非特殊建筑的生成频率和位置。为您的建筑找到合适的类别，然后添加到overmap\_special ID或city\_building ID，并包括生成权重。

```
"abandonedwarehouse": 200,

```

在测试时，如果你想使用自然生成来调查你的工作，你可以提高生成概率。

最后，在提交之前，一定要对添加的内容进行整理。

## mapgen

对于mapgen，其主要为json对象，嵌套式的数组、对象都需要由mapgen主对象进行存放，你可以把mapgen对象理解为存放各种分支变量、参数、对象及数组的容器，它们必须统一嵌套，方便C++函数对Json的直接调用与输入。

### type

定义该对象用于向C++传输mapgen函数向游戏新建新建筑物

仅需将键命名为“type”并对其赐值“mapgen”即可设置此对象的类型为“mapgen”函数

### method

向游戏添加新的建筑物目前有两种方法，一是直接添加至游戏C++函数源码内，二是通过json对象向游戏专为Json所开放的接口进行传输

虽然添加mapgen作为C++函数是快速生成地形的最快（也是最通用的）方式之一，但这需要重新编译游戏，且现在大多数现有的c++建筑都已迁移至json，目前json映射是添加内容和mod的首选方式，所以使用json。

method参数用于指定此mapgen具体存放位置是否位于游戏源码内还是被搁置于json内，所以它有两个参数可选择，分别是“builtin”与“json”

“builtin”参数使用实例：

"mapgen": [ { "method": "builtin", "name": "parking\_lot" } ]

在method参数为“builtin”时，便已确定该mapgen已无需向下编撰更多代码，游戏会根据method所给出的id自动向C++编译源码内寻找相应建筑物，并依据源码设置生成建筑。

如您所编写的建筑物并非直接为编译在C++函数游戏源码内，请不要使用此参数，使用独立的Json对象对游戏内容进行篡改写入的模组使用json，method属性为“json”。

只需要为键“method”赐值字符串“json”，即可编写独立的json-mapgen文件。

### om\_terrain

声明地图的唯一ID，可以用来做大型建筑、小型建筑或建筑嵌套

om\_terrain的值可以使用以下三种方式声明：

* 使用单个字符串赐值地图地形ID
* 数组内编撰多个字符串变量ID列表
* ID嵌套列表

"om\_terrain": "oter\_id"

以此方式声明ID的mapgen建筑范围仅能创建在大地图中的一格24x24建筑范围内

这是最普遍的ID声明方式，但它无法构建类似于电影院、医院、实验室及购物中心这样的大型建筑。

如果你希望建筑能不局限于大地图一格，你可以在同一“om\_terrain”数组中同时声明多个oter\_id变量，请使用以下方式创建：

"om\_terrain": [ "house", "house\_base" ]

可以看到，这个mapgen有两个区域

如果我们想要向y轴（不是z轴，z轴才是高度延伸）上下延伸，需创建更多数组便于使用：

"om\_terrain": [ [ "oter\_id\_1a", "oter\_id\_1b", ... ], [ "oter\_id\_2a", "oter\_id\_2b", ... ], ... ]

多个数组并列在同一数组内，即可完成对y轴的延伸。

在om\_terrain数组内添加id会直接影响到rows，如果只有单一的id，那么rows不能超越24x24格，如果多写几个，如同上面举出的例子那样，数组内添加两个，那rows就是48x48，添加三个，那rows就是72x72。

但类似于道路、铁路等这样的大型线性结构，就不能通过om\_terrain了，见下面的overmap。

### weight（可选）

当游戏随机选取mapgen函数时，每个函数的权重值决定了它的稀有罕见程度（建筑物出现在主世界的概率）。1000是默认值，因此添加权重为“500”的函数将使其出现的频率约为其他使用默认权重的函数的一半。（像10000000这样的极高值对测试很有用，所以请在测试时使用极高的值来方便你进行Debug，否则像军事基地那样的权重值会使你的Debug调试测试工作变得尤为困难）

变量使用数字，实例：

"weight": 1145141919810（好臭的权重值哼哼哼啊啊啊啊啊）

（个人建议：在写完地图mapgen测试时不要把你所写的所有mapgen都丢出来，一个一个测，否则……~~就等着被游戏撅吧（悲）~~）

### fill\_ter

定义地图中未定义的空白地区需要使用什么来进行填充

行内“rows”未定义的字符将会由“fill\_ter”所定义的id填充

变量使用“字符串”，实例：

"fill\_ter": "t\_grass"

### rows

重头戏来了！当你想要定义这个建筑物的样貌、结构时，使用rows“列/行”，绘制ASCII建筑蓝图，是的，mapgen的建筑都是由最为纯粹的ASCII字符串联起来编写而成的，属于ASCII的艺术。

具体使用方法，主要是数组内嵌套式的定义json字符串变量，如"rows": [ "row1...", "row2...", ..., "row24..." ]

rows可以绘制的区域规划具体由om\_terrain编撰，上文已经提到，在没有编写多个oter\_id时最好不要超过24x24范围。

实例：

````
 "rows": [
 ",_____ssssssssssss_____,",
 ",__,__#### ss ####__,__,",
 ",_,,,_#ssssssssss#__,__,",
 ",__,__#hthsssshth#__,__,",
 ",__,__#ssssssssss#_,,,_,",
 ",__,__|-555++555-|__,__,",
 ",_____|.hh....hh.%_____,",
 ",_____%.tt....tt.%_____,",
 ",_____%.tt....tt.%_____,",
 ",_____%.hh....hh.|_____,",
 ",_____|..........%_____,",
 ",,,,,,|..........+_____,",
 ",_____|ccccxcc|..%_____,",
 ",_____w.......+..|_____,",
 ",_____|e.ccl.c|+-|_____,",
 ",_____|O.....S|.S|_____,",
 ",_____#|----w-|-|#_____,",
 ",________,_____________,",
 ",________,_____________,",
 ",________,_____________,",
 " ,_______,____________, ",
 "  ,,,,,,,,,,,,,,,,,,,,  ",
 "   dd                   "
 ],

````

这些字符最好使用等宽的字符，在编写时请事先为你的编辑器开启等宽字体，这些字符不仅仅只局限于ASCII，它同时也允许你使用Unicode字符集，对汉字的兼容性也有，但请确保这个文件使用的是UTF-8，否则不要使用任何特殊字符。在使用这些字符时不使用合适的字符，会给你的编辑造成困难。

### terrain

用于定义行内的地形id，定义“行”的地形id，每个关键字都是带有地形id字符串的单个字符

允许空格 与.点未定义，用于背景fill\_ter，其余的必须进行定义

实例：

```
 "terrain": {
 " ": "t_grass",
 "d": "t_floor",
 "5": "t_wall_glass_h",
 "%": "t_wall_glass_v",
 "O": "t_floor",
 ",": "t_pavement_y",
 "_": "t_pavement",
 "r": "t_floor",
 "6": "t_console",
 "x": "t_console_broken",
 "$": "t_shrub",
 "^": "t_floor",
 ".": "t_floor",
 "-": "t_wall_h",
 "|": "t_wall_v",
 "#": "t_shrub",
 "t": "t_floor",
 "+": "t_door_glass_c",
 "=": "t_door_locked_alarm",
 "D": "t_door_locked",
 "w": "t_window_domestic",
 "T": "t_floor",
 "S": "t_floor",
 "e": "t_floor",
 "h": "t_floor",
 "c": "t_floor",
 "l": "t_floor",
 "s": "t_sidewalk"
 },

```

这些字符内字符串所定义的变量参数皆在声明此地形具体是什么，是地板还是门，是墙还是窗，是破损的还是完好的，胡乱设定这些东西有可能使地图看起来……乱七八糟

实际使用pallette（调色板）可以集中化这些字符，这样就不用在你的mapgen里重复设定这些东西了，既能让你的文件变得精简易于维护，也能缩短加载时间。

不要认为刻意去注意加载时间、便于维护、代码精简没有用处，你这种思想很容易编出💩⛰️代码，有很多公司都因为💩吃过亏，有了前车之鉴就尽量不要在代码旁边拉💩。

### furniture（可选）

当你想要在地图建筑内生成一些凳子、桌子、电脑等家具，使用这个

实例：

```
 "furniture": {
 "d": "f_dumpster",
 "5": "f_null",
 "%": "f_null",
 "O": "f_oven",
 "r": "f_rack",
 "^": "f_indoor_plant",
 "t": "f_table",
 "T": "f_toilet",
 "S": "f_sink",
 "e": "f_fridge",
 "h": "f_chair",
 "c": "f_counter",
 "l": "f_locker"
 },

```

定义这些地形的这个字符中的是什么家具，“f\_null”就是没有

### flags

“flags”标签，用于设置地图在被生成时的一系列的设置，为你的mapgen设置标签

示例：

"flags": [ "ERASE\_ALL\_BEFORE\_PLACING\_TERRAIN" ],

当前定义的标签如下：

ERASE\_ALL\_BEFORE\_LACING\_TERRAIN和ALLOW\_TERRAIN\_UNDER\_OTHER\_DATA是互斥标志，可用于现有地形顶部分层的任何地图生成。这可以是更新mapgen、嵌套mapgen，也可以是带有前置任务的常规mapgen。它指定当更新更改了现有地形，但瓷砖上有现有物品、陷阱或家具时要遵循的行为。如果没有提供任何标志，则这是错误。如果给出ERASE\_ALL\_BEFORE\_LACING\_TERRAIN，则在更改地形之前，将移除所有项目、陷阱或家具。如果给定ALLOW\_TERRAIN\_UNDER\_OTHER\_DATA，则它们将被保留而不会出错。如果您需要对这种行为进行比这些标志所能提供的更细粒度的控制，那么可以单独或一起删除这些内容。请参见下面的其他条目，例如remove\_all。NO\_UNDERLYING\_ROTATE即使基础平铺是，贴图也不会旋转。AVOID\_CREATURES 如果生物存在地形，则不会放置家具和陷阱。

### set（可选）

定义设置地形、家具、陷阱、辐射等的特定命令，阵列按顺序处理。

例子：

```
 "set": [
 { "point": "furniture", "id": "f_chair", "x": 5, "y": 10 },
 { "point": "radiation", "id": "f_chair", "x": 12, "y": 12, "amount": 20 },
 { "point": "trap", "id": "tr_beartrap", "x": [ 0, 23 ], "y": [ 5, 18 ],  "chance": 10, "repeat": [ 2, 5 ] },
 { "point": "variable", "id": "nether_dungeon_door", "x": 4, "y": 2 }
 ]

```

所有X和Y值可以是0到23之间的单个整数，也可以是两个整数[n1，n2]的数组（每个都在0和23之间）。如果将X或Y设置为数组，则结果是该范围（包括该范围）内的随机数。在上述示例中，家具“f\_chair”始终位于坐标“x”：5，“y”：10，但陷阱“tr\_beartrap”在区域“x”:[0，23]，“y“：[5，18]”中随机重复。

其中有几个变量值。

* point

允许写入"terrain", "furniture", "trap", "trap\_remove", "item\_remove", "field\_remove", "radiation", "variable", "creature\_remove"

* id

写入地形、家具或陷阱的id或变量名称

实例："id": "f\_counter", "id": "tr\_beartrap".

使用tr\_null将清除家具

* x,y

XY坐标，0-23之间的值，或该范围内的随机值的范围[0-23，0-23]。示例：“x”：12，“y”：[5，15]

* amount

辐射量，值可设定为0-100范围内

* chance（可选）

N分之一的申请机会

* repeat（可选）

值：[n1，n2]，在n1和n2之间随机生成项目。只有坐标是随机的才有意义。示例：[1，3]-重复1-3次。

#### line

向line（线）内设置内容，示例：

{ "line": "terrain", "id": "t\_lava", "x": 5, "y": 5, "x2": 20, "y2": 20 }

这里的变量多出了一个x2,y2，其中的x,y是起始坐标值，即是起点，x2,y2是线段的终点

由于使用的是“line”，即为“线性的”，所以只能设定一条线段，它可能是斜线，也可能是一条笔直的线，上面的实例便是一条笔直的线。

#### square

设定一个四边形，并在四边形内设置内容

{ "square": "radiation", "amount": 10, "x": [ 0, 5 ], "y": [ 0, 5 ], "x2": [ 18, 23 ], "y2": [ 18, 23 ] }

其中的x,y是四边形的左上角，x2,y2是四边形的右下角

### place\_monster

产生单个怪物，特定怪物或来自怪物组的随机怪物，受怪物生成密度游戏设置的影响。

例子：

```
 "place_monster": [
 { "group": "GROUP_REFUGEE_BOSS_ZOMBIE", "name": "Sean McLaughlin", "x": 10, "y": 10, "target": true }
 ]

```

这将从“group\_REFUGE\_BOSS\_ZOMBIE”组中随机放置一个怪物，将名称设置为“Sean McLaughlin”，在坐标（10，10）处生成该怪物，并将该怪物设置为此次任务的目标。

```
 "place_monster": [
   { "monster": "mon_secubot", "x": [ 7, 18 ], "y": [ 7, 18 ], "chance": 30, "repeat": [1, 3], "spawn_data": { "ammo": [ { "ammo_id": "556", "qty": [ 20, 30 ] } ] } }
 ]

```

这将从“group\_REFUGE\_BOSS\_ZOMBIE”组中随机放置一个怪物，将名称设置为“Sean McLaughlin”，在坐标（10，10）处生成该怪物，并将该怪物设置为此次任务的目标。

```
 "place_monster": [
   { "monster": "mon_secubot", "x": [ 7, 18 ], "y": [ 7, 18 ], "chance": 30, "repeat": [1, 3], "spawn_data": { "ammo": [ { "ammo_id": "556", "qty": [ 20, 30 ] } ] } }
 ]

```

这将“mon\_secubot”放置在随机坐标（7-18，7-18）处，怪物被放置的概率为30%，放置重复随机次数[1-3]，怪物将用20～30发5.56x45mm的子弹生成。

需要注意的是，当使用怪物生成时，高生成密度游戏设置会导致额外的怪物生成，当使用组时，只会产生一只怪物。

属性：

* monster

要生成的怪物的ID

* group

要生成的怪物组ID，在怪物组中根据怪物组代码中的设置权重进行随机生成

* x,y

怪物生成的位置，如果坐标设置为矩形，怪物将会在矩形区域内随机生成，例如："x": 12, "y": [ 5, 15 ]

* chance

生成的概率

* repeat

怪物生成多少次，可以是数字或范围

* pack\_size

有多少怪物诞生，可以是单个数字或范围，如[1-4]，受几率和怪物生成密度的影响，从组生成时忽略

* one\_or\_none

由于生成密度高，不允许多个生成，如果未定义重复或定义了包大小，则默认为true，否则默认为false，从组生成时忽略。

* friendly

设置为true可使生成后的怪物为友好状态（想象一只对你非常友好的浩克），默认为false

* name

要在怪物身上所显示的额外的名称

* target

设置为true，使其成为任务目标，只有当怪物从任务中诞生时才有效

* span\_date

一个可选对象，包含用于生成怪物的其他详细信息

其中span\_date需要再设置一个对象，具体设置方法如下

* ammo

一个对象列表，每个对象都有一个“amm\_id”字段和一个包含两个整数的“qty”列表。怪物将用“ammon\_id”的物品进行生成，“数量”中至少有第一个数字，但不超过第二个数字

* patrol

对象列表，每个对象都有一个“x”字段和一个“y”字段，值可以是范围或单个数字，x,y坐标将巡逻点定义为与怪物生成的覆盖地图地形块的（0，0）局部地图方格偏移的相对地图方格点，巡逻点在怪物生成器内转换为绝对地图方格三点

有巡逻点列表的怪物会按顺序移动到每个巡逻点，每当他们没有更紧迫的行动要轮到他们时。到达巡逻点列表中的最后一个点后，怪物将继续到列表中的第一个点。

例子：

```
 "place_monster": [
   { "monster": "mon_zombie", "x": 12, "y": 12, "spawn_data": { "patrol": [ { "x": 12, "y": 12 } ] } }
 ]

```

这将在（12，12）处放置一个“mon\_zombie”。僵尸可以自由移动以追逐敌人，但如果它没有其他事情可做，它将始终返回（12，12）位置。

例子：

```
 "place_monster": [
   { "monster": "mon_secubot", "x": 12, "y": 12, "spawn_data": { "ammo": [ { "ammo_id": "556", "qty": [ 20, 30 ] } ], "patrol": [ { "x": -23, "y": -23 }, { "x": 47, "y": -23 }, { "x": 47, "y": 47 },  { "x": 47, "y": -23 } ] } }
 ]

```

这将在（12,12）处放置一个“mon\_secubot”。它将以方框模式巡视对角相邻的重叠地形瓦片的四个最突出的问题。

### place\_monsters

与“place\_monster”的功能及用法类似，关键区别在于“place\_monsters”保证每一个有效条目都是派生的，且只使用怪物组，请不要将此变量用作大批量生成怪物中，怪物数量受到多方面因素影响是非常难以进行控制的。

* monster

您希望生成怪物组的ID

* x,y

生成区域的矩形或特定范围，值在0～23间，如设定为0-23将会在一个区域内随机选取生成怪物的坐标值。

* chance

表示整个组产生的概率为N分之一，每次重复一次，如果随机数生成失败，指定的整个组将不会产生，保留空白以保证怪物稳定生成。

* repeat

怪物的生成会重复多次，可以是数字或范围，同样，这表示组将产生的次数。

* density

这个数字乘以玩家所在世界的生成密度，然后概率四舍五入以确定该群体的生成次数，每次重复生成时都会执行此操作，例如，如果此计算的最终乘数为2，重复值为6，则该组将产生2\*6或12次。

### place\_item（可选）

在特定的位置中设置项目（WIP：怪物和载具都可以）

```
   "place_item": [
   { "item": "weed", "x": 14, "y": 15, "amount": [ 10, 20 ], "repeat": [1, 3], "chance": 20 }
   ]

```

* item

要生成的物品ID

* x,y

在特定的坐标中或在一定范围内随机选取坐标生成内容

* amount

要生成物品的随机数量，可以是特定的整数也可以是范围内的随机数

* chance（可选）

物品有N分之一机会生成

* repeat（可选）

值：[n1，n2]。在n1和n2之间随机繁殖项目。只有坐标是随机的才有意义。示例：[1，3]-重复1-3次

* custom-flags（可选）

为生成的物品设定flags

特殊自定义标志“ACTIVATE\_ON\_PLACE”会在放置项目时激活该物品，这对于在玩家接近时已经开启的噪声发生器非常有用，它还可以与爆炸物一起使用，倒计时1秒，以便在玩家接近时使位置爆炸，从而创建独特的破坏地形。

### <type-of-special> （可选）

特殊的地图功能，不仅仅是放置家具/地形。

可以使用上面的“rows”条目通过地形/家具映射之类的映射或通过其坐标的精确位置来定义特殊。

映射是用如下的json对象定义的：

```
   "<type-of-special>" : {
   "A" : { <data-of-special> },
   "B" : { <data-of-special> },
   "C" : { <data-of-special> },
   ...
   }

```

“＜type-of-special＞”是下面列出的类型之一，“<date-of-special>”的数据是一个json对象，其内容特定于特殊类型。有些类型根本不需要数据，或者它们的所有数据都是可选的，一个空对象就足以满足这些特殊性。您可以定义任意数量的映射。

每个映射都可以是一个数组，对于可能在平铺上出现多次的对象（例如物品、字段），数组的每个条目都按顺序应用。对于陷阱、家具和地形，随机选择一个条目（所有条目都有相同的机会）并应用。

示例（在所有“.”中有2/3概率放置草，有1/3概率放置土）：

```
   "terrain" : {
   ".": [ "t_grass", "t_grass", "t_dirt" ]
   }

```

还可以直接指定实例的数量（以及它们的概率），这对于罕见的情况特别有用（而不是多次重复公共值）：

```
   "fields" : {
   ".": [ { "field": "fd_blood" }, { "field": "fd_bile" } ]
   }

```

~~（什么生草翻译，但我自己翻译出来的东西比谷歌翻译还要抽象，只能用度娘力（悲））~~

或者一次定义一个字符的映射：

```
   "mapping" : {
   ".": {
       "traps": "tr_beartrap",
       "field": { "field": "fd_blood" },
       "item": { "item": "corpse" },
       "terrain": { "t_dirt" }
   }
   }

```

如果你想把很多不同类型的东西放在一个地方，这可能会更有用。

~~我彻底摆烂，这些翻译生草文字自己应该能看懂的对吧~~

通过特定位置定义特价商品：

```
   "place_<type-of-special>" : {
   { "x": <x>, "y": <y>, <data-of-special> },
   ...
   }

```

<x>和<y>定义特殊对象的放置位置（x是水平的，y是垂直的）。有效值在0..23范围内，也支持min-max值：“x”：[0，23]，“y”：[0，23]将特殊值放在地图上。

映射示例（字符“O”和“；”应出现在特殊字符应出现的行数组中）：

```
   "gaspumps": {
   "O": { "amount": 1000 }
   },
   "toilets": {
   ";": { }
   }

```

放置在厕所中的水量是可选的，因此空入口是完全有效的。

坐标示例：

```
   "place_gaspumps": [
   { "x": 14, "y": 15, "amount": [ 1000, 2000 ] }
   ],
   "place_toilets": [
   { "x": 19, "y": 22 }
   ]

```

地形、家具和陷阱可以指定为单个字符串，而不是json对象：

```
   "traps" : {
   ".": "tr_beartrap"
   }

```

类似于这样：

```
   "traps" : {
   ".": { "trap": "tr_beartrap" }
   }

```

将烟雾、气体或血液与“字段”一起放置，类似于这样的示例：

```
   "place_fields": [ { "field": "fd_blood", "x": 0, "y": 0, "intensity": [ 1, 3 ], "repeat": [ 0, 3 ] } ]
   "place_fields": [ { "field": "fd_blood", "x": 0, "y": 0, "intensity": 1, "repeat": [ 0, 3 ] } ]

```

属性剖析：

* filed

（必需的字符串）字段类型（例如“fd\_blood”、“fd\_smoke”）

* density

（可选，整数）场密度。默认值为1。可能的值为1、2或3。

* intensity

（可选、整数、数组）字段的集中程度，从1到3或更多。阵列是随机的。参见data/json/field\_type.json

* age

（可选，整数）字段年龄。默认值为0。

* remove

（可选，布尔）如果为true，则将删除而不是添加给定字段，默认为false。

下面的几个分类都是它：

#### npcs

用“npcs”向地图内放置NPC

例子：

"npcs": { "A": { "class": "NC\_REFUGEE", "target": true, "add\_trait": "ASTHMA" } }

属性解析：

* class

（必需，字符串）npc类id，请参阅data/json/npcs/npc.json或定义自己的npc类。

* target

（可选，bool）这个NPC是一个任务目标，仅对update\_mapgen有效，默认false。

* add\_trait

（可选，字符串或字符串数组）除了类定义中的任何特征之外，此NPC还具有这些特征

* unique\_id

（可选，字符串）这是描述npc的唯一id，如果具有此id的npc已经存在，则命令将自动失败。

#### signs

放置一个写有消息的标志（furniture f\_sign），必须定义“标志”或“片段”。消息中可能包含标签，如＜full\_name＞、＜given\_name＞和＜family\_name＞，这些标签将插入随机生成的名称，或＜city＞，它们将插入最近的城市名称。

"signs": { "P": { "signage": "Subway map: <city> stop" } }

* signage

（可选，字符串）应显示在标志上的消息。

* snippet

（可选，字符串）可以出现在标志上的代码段类别。

#### vendingmachines

放置自动售货机和带有“售货机”的物品，放置自动售货机（家具），并将其装满物品组中的物品。

* item\_group

（可选，字符串）用于在计算机内创建项目的项目组。默认为“vending\_food”或“vending\_drink”（随机选择）。

* reinforced

（可选，布尔）设置，这将使自动售货机在加固后生成，默认为false。

* lootable

（可选，布尔）设置，指示该特定自动售货机是否有机会产生被洗劫的物品（即破损且里面没有物品）大灾变之后，这种可能性会随着每一天的流逝而增加，仅当加固为假时有效，默认为false。

#### toilet

放置一个装有~~老八伤心时喝的酒水~~水的马桶

* amount

（可选，整数或最小/最大数组）放置在马桶中的水量，可以直接设零说没有，但是你为什么还要多此一举的添加属性呢？=）

#### gaspumps

放置一个加油泵或柴油泵，并用“气筒”加油

* amount

（可选，整数或最小/最大阵列）泵中的燃油量。如果未指定，则将金额随机分配在10000和50000之间。

* fuel

（可选，字符串：“汽油”、“柴油”、“jp8”或“avgas”）要放入泵中的燃料类型。如果未指定，则燃油为汽油（75%的可能性）或柴油（25%的可能性）。

#### items

放置物品组

* item

（必需，字符串或itemgroup对象）要使用的项目组。

* chance

（可选，整数或最小/最大数组）循环将继续从组中生成项目的概率为x（根据其类型，循环本身可能会生成多个项目或不生成多个，请参见ITEM\_spawn.md），除非概率为100，在这种情况下，它将触发物品组恰好生成一次（请参见map::place\_items）。

* repeat

（可选，整数或min/max数组）重复此放置的次数，默认值为1。

* faction

（可选，字符串）拥有这些物品的派系。

#### monsters

放置怪物组中的怪物，加载地图时怪物就会出现

* monster

（必选，字符串）一个怪物组id，当地图加载时，该组中的随机怪物将被生成在地图。

* density

（可选，浮动）如果已定义，它将覆盖该位置的默认怪物密度（怪物密度朝向城市中心更大）（请参见map::place\_spawns）。

* chance

（可选，整数或最小/最大数组）创建繁殖点的几率为1/x（请参见map:：place\_spawn）。

#### vehicles

* vehicle

（必填，字符串）车辆类型或车辆组id。

* chance

（可选的，整数或最小/最大数组）乘以车辆生成的概率为100%。默认值为1（这意味着车辆产生的概率为1%，您可能需要更大的车辆）。

* rotation

（可选，整数）车辆面向的方向。

* fuel

（可选，整数）燃油状态。默认值为-1，这将使储罐充满1-7%，正值被解释为车辆油箱的填充百分比（例如，100表示完全充满）。

* status

（可选，整数）默认值为-1（轻微损坏），值0表示完好，1表示严重损坏。

* faction

（可选，字符串）此车辆的派系主人

请注意，不能将车辆放置在过映射边界上，所以它最多需要24格。

```
   "place_vehicles": [
   { "vehicle": "fire_engine", "x": 11, "y": 13, "chance": 30, "rotation": 270 }
   ]

```

##### remove\_vehicles

移除地图中的某一车辆或所有车辆

* vehicles

（可选，字符串数组）要移除的车辆类型，如果留空，所有车辆将被移除。

```
   "remove_vehicles": [
   { "vehicles": [ "fire_engine" ], "x": [ 10, 15 ], "y": [ 10, 15 ] }
   ]

```

#### item

使用item放置特定物品

* item

（必需，字符串）新建物品的物品类型id。

* chance

（可选，整数或最小/最大数组）该物品将产生的概率为x。默认值为1，值“1”意味着它将始终生成。

* amount

（可选，整数或最小/最大数组）要生成的项目数，默认值为1。

* repeat

（可选，整数或min/max数组）重复此放置的次数，默认值为1。

要将此类型与显式坐标一起使用，请使用名称“place\_item”（这是为了向后兼容），如下所示：

```
   "item": {
   "x": { "item": "rock" }
   },
   "place_item": [
   { "x": 10, "y": 1, "item": "rock" }
   ]

```

#### monster

放置怪物

* monster

（必需，字符串）怪物的类型id（例如mon\_zombie）。

* friendly

（可选，布尔）怪物是否友好，默认值为false。

* name

（可选，字符串）该怪物的名称，可选，默认值是创建一个未命名的怪物。

* target

（可选，布尔）这个怪物是任务目标。仅对update\_mapgen有效。

#### traps

放置陷阱

* trap

（必需，字符串）陷阱的类型id（例如tr\_beartrap）。

* remove

（可选，布尔）如果为true，则将删除而不是添加给定的陷阱，默认为false。

#### furniture

放置家具

* furn

（必需，字符串）家具的类型id（例如f\_chair）。

#### terrain

如果地形设置了值“屋顶”，并且位于封闭空间中，则为室内。

* ter

（必需，字符串）地形的类型id（例如t\_floor）。

#### rubble

创建碎石并冲击现有地形（在设置家具/地形等其他事物后，最后应用此步骤）。创建碎石会调用撞击功能，从而破坏地形并导致建筑物倒塌。

* rubble\_type

（可选，furniture id，默认值：f\_bracles）创建的碎石的类型。

* items

（可选，布尔，默认值：false）放置冲击结构产生的物品。

* floor\_type

（可选，地形id，默认值：t\_dirt）仅在该位置有不可撞击的墙或overwrite=true时使用。

* overwrite

（可选，布尔，默认值：false）如果为true，则只在当前存在的内容之上写入。

要将此类型与显式坐标一起使用，请使用名称“place\_rubble”（无复数），如下所示：

```
   "place_rubble": [
   { "x": 10, "y": 1 }
   ]

```

#### place\_liquids

在指定位置创建液体项目，液体目前不能被收集（除了罐或泵中的汽油，或者除非液体溅到的地面上有LIQUIDCONT标志），但可以用来为mapgen添加与情景标配的环境。

* liquid

（必需，项目id）项目（液体）

* amount

（可选，整数/最小最大数组）要放置的液体量（值-1默认为项目的默认电荷）

* chance

（可选，整数/最小最大数组）产生液体的几率为N分之一，默认值为1（100%）

将默认数量的汽油（200单位）扔到地面上的示例（通过使用行数组中的字符或显式坐标）：

```
   "liquids": {
   "g": { "liquid": "gasoline" }
   },
   "place_liquids": [
   { "liquid": "gasoline", "x": 3, "y": 5 }
   ],

```

#### loot

放置项目组或单个项目中的项目。这与place\_item和item/items之间的一个重要区别是，战利品可以从分发组中产生单个项目（无循环）。它还可以产生一个匹配的弹匣和枪支弹药。

注意：必须指定物品组或物品，但不能同时指定两者。

* group

（string）要使用的项目组（有关集合与分发组的说明，请参见item\_SPAWN.md）

* item

（string）要生成的项的id类型

* chance

（可选，整数）每100个物品生成的机会。默认值为100。

* ammo

（可选，整数）在默认弹药量下，每100个物品生成的机会中。默认值为0。

* magazine

（可选，整数）x在默认弹匣中产生物品的概率为100，默认值为0。

* variant

派生项的类型变量id

#### sealed\_item

将物品或物品组放置在对项目进行特殊处理的家具中。

这适用于带有plant标志的家具，如f\_plant\_harvest，因为通过其他方式将物品放置在此类家具上不会起作用（因为它们带有NOITEM标志）。

在这样的家具上，应该有一个单独的（隐藏的）种子项目来指示植物的种类。使用sealed\_item，可以通过指定家具和种子项来创建这样的植物。

注意：必须仅给出“物品”或“物品组”中的一个（但不能同时给出两者）。

* furniture

（字符串）所选家具的id

* item

将项目派生为特殊“物品”

* items

生成一个物品组作为“物品”特殊项。

例子：

```
 "sealed_item": {
 "p": {
   "items": { "item": "farming_seeds", "chance": 100 },
   "furniture": "f_plant_harvest"
 }
 },

```

#### graffiti

在该位置放置涂鸦消息。必须定义“文本”或“代码段”。消息中可能包含标签，如＜full\_name＞、＜given\_name＞和＜family\_name＞，这些标签将插入随机生成的名称，或＜city＞，它们将插入最近的城市名称。

* text

（可选，字符串）将放置的消息。

* snippet

（可选，字符串）将从中提取消息的片段类别。

#### zone

派系中的NPC将使用该区域影响AI。

* type

（必需，字符串）值：“NPC\_RETREAT”、“NPC\_NO\_INVESTIGATE”或“NPC\_INVESTIGATE\_ONLY”或LOOT\_xxx

* faction

（必填，字符串）将使用该区域的NPC派系的派系id。

* name

（可选，字符串）区域的名称。

* filter

（可选，字符串）用作LOOT\_CUSTOM的筛选器，或用作LOOT\_ITEM\_group的组id

“type”字段值影响NPC行为。NPC将：

* 倾向于向NPC\_RETREAT区域撤退。

* 不要移动以查看来自NPC\_NO\_INVESTIGATE区域的不可见声音的来源。

* 不要移动以查看来自NPC\_INVESTIGATE\_ONLY区域之外的未看见声音的来源。

* 为他们的商店使用LOOT\_xxx区域（请参见NPC.md#shop\_restocking）

与货运车辆部件重叠的单点掠夺区将作为车辆区。

通过打开调试模式并在区域管理器中更改势力，可以在游戏中调试区域布局。

#### zones

~~生草翻译：拿“区域”教导球员分娩地点~~在设计场景时，您可以使用ZONE\_START\_POINT区域直接指定玩家在地图中的位置，玩家将被放置在此区域的中心，ZONE\_START\_POINT区域仅在属于your\_followers派系时才被视为有效，请记住，使用此方法指定玩家生成的位置时，不会进行额外的检查，因此玩家可以在墙上、露天或其他不合适的地点中被生成。

#### remove\_all

这没有其他字段，将从地图中删除所有“fields, items, traps, graffiti, furniture”。这在例如nest或其他更新mapgen中很有用，以清除可能存在但在nest中没有意义的现有内容。

#### translate\_ter

将一种地形类型转换为另一种地形。没有理由用普通mapgen这样做，但这对于使用update\_mapgen设置基线非常有用。

* from

（必选，字符串）要转换的地形的地形id

* to

（必选，字符串）源地形将转换为的地形id

#### ter\_furn\_transforms

在指定位置运行ter\_furn\_transform。这对于作为update\_mapgen的一部分应用变换非常有用，因为普通mapgen只能直接指定地形。

* “transform”：（必选，字符串）要运行的ter\_furn\_transform的id。

#### place\_nested

Place\_nested允许基于其过映射邻居的“id”和用于放置可变过映射特殊对象的连接，对块进行有限的条件派生。这对于在生物群落类型之间创建更平滑的过渡或在可变结构的边缘动态创建墙非常有用。

* chunk/else\_chunk

（必需，字符串）将有条件放置的块的nested\_mapgen\_id。如果指定的邻居匹配，则放置块，否则放置“else\_chunk”。

* x,y

（必要，int数字）将放置块的主要位置。

* neighbors

（可选）放置块之前应检查的任何相邻过盈。每个方向都与覆盖映射“id”子字符串的列表相关联。

* joins

（可选）在放置块之前应检查的任何可变过映射特殊连接。每个方向都与连接“id”字符串列表相关联。

可以通过这种方式检查的相邻的外包装是：

* 直接的主要临近（“北”、“东”、“南”、“西”），

* 基数间临近（“north\_east”、“north\_west”、“south\_east”、“south\_west”）

* 直接垂直相邻（“上方”、“下方”）。

只能检查主方向“上方”和“下方”的连接

例子：

```
   "place_nested": [
   { "chunks": [ "concrete_wall_ew" ], "x": 0, "y": 0, "neighbors": { "north": [ "empty_rock", "field" ] } },
   { "chunks": [ "gate_north" ], "x": 0, "y": 0, "joins": { "north": [ "interior_to_exterior" ] } },
   { "else_chunks": [ "concrete_wall_ns" ], "x": 0, "y": 0, "neighbors": { "north_west": [ "field", "microlab" ] } }
   ],

```

上面的代码摘录将按如下方式放置块：

* “concrete\_wall\_ew”，如果北边临近的是田野或实心岩石

* “gate\_north”，如果在可变覆盖映射放置期间将连接“interior\_to\_extrior”用于北面

* 如果西北邻近既不是油田，也不是任何微型实验室，则为“混凝土墙”

#### place\_corpses

从怪物群中创建一具随机怪物尸体

* group

（必选，字符串）将从中选择随机怪物的怪物组id

* age

（可选，整数）怪物尸体的年龄（天）。如果未设置，则默认为当前转弯

放置怪物尸体的示例（使用行数组中的字符或显式坐标）：

```
   "corpses": {
   "g": { "group": "GROUP_PETS", "age": 3 }
   },
   "place_corpses": [
   { "group": "GROUP_PETS", "x": 3, "y": 5 }
   ],

```

#### computers或place\_computers

创建f\_console家具。尽管唯一需要的字段是name，但您还应该定义选项或（eocs和chat\_topics），以便与计算机进行交互

* name

（必需，字符串）计算机的名称

* options

（可选，对象数组）一组可供玩家使用的选项，name（string）-显示选项的名称，action-来自computer\_session.cpp的硬编码操作的id

* failures

（可选，对象数组）在黑客尝试失败的情况下可能发生的一组失败，action-来自computer\_session.cpp的硬编码计算机故障的id，每一次失败的黑客尝试只能发生一次随机故障

* security

（可选，整数）值，用于确定黑客攻击此计算机的难度。它与玩家的计算机技能和智力进行了对比

* access\_denied

如果安全性>0，则向玩家显示（可选，字符串）消息，默认为“错误！访问被拒绝！”

* eocs

（可选，字符串数组）当玩家检查计算机时将产生的效果的名称

* chat\_topics

（可选，字符串数组）对话主题（如果使用计算机打开对话框）

放置计算机控制台的示例（使用行数组中的字符或显式坐标）：

```
 "computers": {
 "a": {
   "name": "Test computer 1",
   "security": 3,
   "options": [ { "name": "Test unlock action", "action": "unlock" } ],
   "failures": [ { "action": "shutdown" }, { "action": "alarm" } ],
   "access_denied": "ERROR!  Access denied!  Unauthorized access will be met with lethal force!"
 }
 },
 "place_computers": [
 {
   "name": "Test computer 2",
   "eocs": [ "EOC_REFUGEE_CENTER_COMPUTER" ],
   "chat_topics": [ "COMP_REFUGEE_CENTER_MAIN" ],
   "x": 20,
   "y": 20
 }
 ],

```

### mapgen的值

mapgen值可用于需要特定id的各种位置。例如，参数的默认值，或“terrain”对象中的地形id。mapgen值可以采用以下三种形式之一：

* 一个简单的字符串，应该是一个文本id，例如，“t\_flat\_roof”

* 一个包含关键字“distribution”的JSON对象，其对应值是一个列表列表，每个列表都包含一对字符串id和一个整数权重。例如：

{ "distribution": [ [ "t\_flat\_roof", 2 ], [ "t\_tar\_flat\_roof", 1 ], [ "t\_shingle\_flat\_roof", 1 ] ] }

* 包含键“param”的JSON对象，其对应值是Mapgen参数中讨论的参数的字符串名称。例如，｛“param”：“roof\_type”｝。您可能还需要提供回退值，例如｛“param”：“roof\_type”，“fallback”：“t\_flat\_roof”｝。为了在不破坏正在进行的游戏的情况下更改mapgen定义，回退是必要的。可以在不同的时间生成同一个overmap special的不同部分，如果在生成过程中向定义部分添加了新参数，则该参数的值将丢失，将使用回退。

* 根据其他mapgen值的值选择不同值的switch语句。这通常用于打开mapgen参数的值，以便允许mapgen的两个部分保持一致。例如，以下开关将使栅栏门类型与mapgen参数fence\_type选择的栅栏类型相匹配：

```
   {
   "switch": { "param": "fence_type", "fallback": "t_splitrail_fence" },
   "cases": {
       "t_splitrail_fence": "t_splitrail_fencegate_c",
       "t_chainfence": "t_chaingate_c",
       "t_fence_barbed": "t_gate_metal_c",
       "t_privacy_fence": "t_privacy_fencegate_c"
   }
   }

```

### mapgen参数

（请注意，此功能正在开发中，功能可能与文档不完全一致）

mapgen定义或调色板中的另一个条目可以是“parameters”键。例如：

```
 "parameters": {
 "roof_type": {
   "type": "ter_str_id",
   "default": { "distribution": [ [ "t_flat_roof", 2 ], [ "t_tar_flat_roof", 1 ], [ "t_shingle_flat_roof", 1 ] ] }
 }
 },

```

“parameters”JSON对象中的每个条目都定义了一个参数。关键是参数名称。每个这样的键都应该有一个关联的JSON对象。该对象必须提供其类型（对于cata\_variant应该是类型字符串），并且可以选择提供默认值。默认值应该是上面定义的mapgen值。

在编写本文时，参数获取值的唯一方法是通过“默认值”，所以您可能希望始终有一个值。

参数的主要应用是，您可以使用“distribution”mapgen值随机选择一个值，然后将该值应用于该参数的每次使用。在上面的示例中，拾取了一个随机的屋顶地形。通过将参数与一些“地形”键一起使用，通过“param”mapgen值，可以在地图上使用随机但一致的屋顶地形选择。相反，将“分布”直接放置在“地形”对象中会导致mapgen为每个屋顶瓦片随机选择一个地形，从而导致屋顶地形的混乱。

默认情况下，参数的范围是生成的overmap\_special。也就是说，该参数在overmap\_special中具有相同的值。当需要默认值时，将在生成该特殊的第一个块时选择该值，并且该值将被保存以供以后的块重用。

如果您愿意，可以指定“scope”：“omt”以将作用域限制为仅一个覆盖图块。然后将为每个OMT单独选择默认值。这样做的优点是，当在mapgen中使用该参数时，您不再被迫选择“回退”值。

作用域的第三个选项是“scope”：“nest”。这只有在嵌套mapgen中使用时才有意义（尽管在其他地方使用它并不是错误，这样嵌套和非嵌套mapgen可以使用相同的调色板）。当作用域为嵌套时，将为特定的嵌套块选择参数值。例如，假设一个嵌套定义了多个平铺的地毯，您可以使用一个参数来确保该嵌套中所有平铺的地毯都是相同的颜色，但同一OMT中其他位置的同一nested\_mapgen\_id的另一个实例可能会选择不同的颜色。

为了帮助您调试mapgen参数及其对mapgen的影响，您可以在overmap编辑器中查看overmap\_special-scoped参数的选定值（可通过调试菜单访问）。

### rotation

完成所有其他mapgen工作后，旋转生成的地图。该值可以是单个整数或范围（从中随机选择一个值）示例：“旋转”：[0，3]

它将会旋转90°

### predecessor\_mapgen

在此处指定一个过映射地形id将首先为该过映射地形类型运行整个mapgen，然后再应用此处定义的其余mapgen。这方面的主要用例是当我们的位置地图生成发生在森林、沼泽或湖岸等自然特征中时。许多现有的JSON mapgen试图模拟它们所放置的类型的mapgen（例如，森林中的一个小屋放置了森林中的树木、草地和杂乱的东西，以尝试使小屋适合），这导致当该类型的生成发生变化时，它们不同步。通过指定preducer\_mapgen，您可以转而关注添加到现有位置类型的内容。

例子: "predecessor\_mapgen": "forest"

#### fallback\_predecessor\_mapgen

如果您的地图可以存在于各种环境中，那么您可能希望自动利用mapgen来获取在设置此地形之前假设的任何地形。例如，超地图专用工具总是放置在现有地形上，如田地和森林。

定义“fallback\_preedessor\_mapgen”允许您的地图选择请求，无论以前的地形是什么，都应首先生成地形，然后再将mapgen应用于顶部。这与上述“predepressor\_mapgen”的工作原理相同，只是它会自动为上下文选择正确的地形。

然而，为了支持跨mapgen定义更改的存储游戏迁移，您必须提供一个回退值，该值将在游戏不知道先前地形的情况下使用。

例子："predecessor\_mapgen": "field"

## palettes

调色板提供了一种对不同的mapgen使用相同符号定义的方法。例如，CDDA中定义的大多数房屋都是standard\_domestic\_palette。例如，该选项板将h定义为f\_chair的含义，因此所有house mapgen都可以在其“rows”数组中使用h，而无需在任何地方重复此定义。它只需要引用调色板，通过添加

"palettes": [ "standard\_domestic\_palette" ]

每个房子的定义。

每个mapgen都可以引用多个选项板。当两个选项板都定义了同一符号的含义时，将应用这两个选项。在某些情况下（例如生成项），您可以在最终输出中看到两者的结果。在其他情况下（例如设置地形或家具），一个结果必须覆盖其他结果。规则是，列出的最后一个选项板将覆盖先前的选项板，外部mapgen中的定义将覆盖其中选项板中的任何内容。

调色板定义可以包含上面针对JSON对象定义描述的任何JSON，其中定义了符号的含义。它们不能为特定位置指定任何内容（使用“x”和“y”坐标）。

调色板本身可以通过“palettes”键包含其他调色板。因此，如果两个或多个调色板具有许多相同的符号，这些符号具有相同的含义，则可以将公共部分拉出到每个选项板都包含的新选项板中，这样定义就不必重复。

### mapgen调取调色板

“palettes”列表中的值不需要是简单的字符串，它们可以是如上所述的任何mapgen值，最重要的是，这意味着他们可以使用“分布”从一组调色板中随机选择。

此选择的工作方式就像是一个覆盖映射特殊范围的mapgen参数，因此，特殊中的所有OMT将使用相同的调色板，此外，通过查看overmap编辑器中显示的overmap特殊参数（可通过调试菜单访问），您可以看到选择了哪个调色板。

例如，客舱mapgen定义中使用了以下JSON

```
   "palettes": [ { "distribution": [ [ "cabin_palette", 1 ], [ "cabin_palette_abandoned", 1 ] ] } ],

```

使生成的一半舱室使用常规舱室调色板，另一半舱室使用舱室调色板。

### 调色板的使用

首先，为对象创建一个键名为“type”的变量，字符串赐值“palette”

赐值类型为调色板后，为调色板赐值它独有的、不重复的、唯一的ID

#### terrain

指定mapgen中的各个ASCII字符都代表什么

示例：

```
 "terrain": {
     ".": [ [ "t_region_groundcover", 50 ], [ "t_region_shrub", 2 ], "t_region_tree" ],
     "#": "t_region_shrub",
     "&": [ [ "t_wall_wood_broken", 4 ], "t_wall_wood_chipped" ],
     "+": [ [ "t_door_c", 2 ], [ "t_door_o", 2 ], "t_door_boarded", "t_door_boarded_damaged" ],
     "-": [ [ "t_wall_wood_chipped", 4 ], "t_wall_wood" ],
     ":": "t_fencegate_c",
     "~": [ "t_swater_sh", [ "t_covered_well", 3 ], "t_water_pump" ],
     "0": "t_window_empty",
     "1": "t_region_tree",
     "4": "t_region_tree_evergreen",
     "5": "t_region_tree_evergreen",
     "6": "t_region_tree_fruit",
     "7": "t_tree_dead",
     "8": "t_region_tree_nut",
     "^": "t_dirtfloor",
     "_": "t_dirtfloor",
     "=": "t_dirtfloor",
     "{": "t_dirtfloor",
     "%": [ [ "t_wall_wood_broken", 4 ], "t_wall_wood_chipped" ],
     "!": "t_dirtfloor",
     "a": "t_region_groundcover",
     "b": "t_dirtfloor",
     "B": "t_door_boarded",
     "c": "t_dirtfloor",
     "d": "t_region_groundcover_barren",
     "D": "t_door_boarded_damaged",
     "f": "t_region_groundcover",
     "h": "t_dirtfloor",
     "I": "t_dirtfloor",
     "L": [ "t_covered_well", [ "t_water_pump", 2 ] ],
     "M": "t_milking_machine",
     "n": "t_dirtfloor",
     "N": "t_dirtfloor",
     "O": "t_column",
     "p": "t_region_groundcover",
     "P": "t_dirtfloor",
     "r": "t_region_groundcover",
     "R": "t_dirtfloor",
     "s": "t_dirtfloor",
     "S": "t_dirtfloor",
     "t": "t_region_tree",
     "T": "t_dirtfloor",
     "u": "t_dirtfloor",
     "v": "t_fence_h",
     "Q": "t_bulk_tank",
     "w": "t_window_boarded_noglass",
     "W": "t_window",
     "|": [ [ "t_wall_wood", 4 ], "t_wall_wood_chipped" ],
     "<": "t_ladder_up",
     ">": "t_ladder_down"
   },

```

它是定义了一个对象，而这个对象内部含有palette对各个字符的定义

#### furniture

其中的什么符号里放什么家具，与上面的地形用法一致。

示例：

```
 "furniture": {
     ".": [ [ "f_null", 100 ], "f_region_weed", "f_boulder_small", "f_boulder_medium" ],
     "=": "f_smoking_rack",
     "^": "f_rubble",
     "{": "f_rack",
     "%": "f_rubble",
     "a": "f_rubble_rock",
     "A": "f_straw_bed",
     "b": "f_brazier",
     "c": "f_clay_kiln",
     "C": "f_crate_o",
     "f": "f_region_weed",
     "g": "f_generator_broken",
     "h": "f_hay",
     "I": "f_stool",
     "!": "f_canvas_door_o",
     "m": "f_machinery_old",
     "n": "f_canvas_floor",
     "N": "f_canvas_wall",
     "r": "f_rubble",
     "R": "f_rubble_rock",
     "s": "f_straw_bed",
     "S": "f_still",
     "T": "f_table",
     "u": "f_utility_shelf"
   }

```

“.”的定义为1/3概率选出地形。

## update\_mapgen

update\_mapgen是普通JSON mapgen的变体。它不创建新的覆盖映射图块，而是使用一组特定的更改更新现有的覆盖映射片。

update\_mapgen通常使用与JSON mapgen相同的字段，只有少数例外。updatemapgen有几个新字段来支持任务，以及指定将更新哪个overmap图块的方法。

### over\_map

update\_mapgen更新现有的覆盖贴图平铺。这些字段提供了一种指定要更新的磁贴的方法。

#### assign\_mission\_target

assign\_mission\_target将覆盖图块指定为任务的目标。同一范围内的任何update\_mapgen都将更新该覆盖映射图块。将使用具有所需地形ID的最近覆盖地图地形，如果没有匹配的地形，将创建om\_special类型的覆盖地图特殊地形，然后将使用该特殊地形中的om\_terrain。

* om\_terrain

（必填，字符串）任务目标的覆盖地图地形ID

* om\_special

（必填，字符串）任务目标的过映射特殊ID

#### om\_terrain

将使用om\_special类型的最近二次映射专用中om\_terrain类型的最近一次映射平铺。将更新覆盖图块，但不会将其设置为任务目标。

* om\_terrain

（必填，字符串）任务目标的覆盖地图地形ID

* om\_special

（必填，字符串）任务目标的过映射特殊ID

### target

update\_mapgen为一些mapgen JSON项添加了新的可选关键字。

place\_npc、place\_mnster和place\_computer可以采用可选的目标布尔值。如果它们具有“target”：true，并且update\_mapgen使用有效任务调用它们，则NPC、怪物或计算机将被标记为任务的目标。

### map\_extra

额外的地图可以用来放置环境物体和结构，有助于创建一些突发事件及故事情节，它们在地图被探索时被随机放置，从简单的池塘和树林到满载敌人或NPC的坠毁飞船。

```
 {
 "id": "mx_minefield",
 "type": "map_extra",
 "name": { "str": "Minefield" },
 "description": "Mines are scattered here.",
 "generator": { "generator_method": "map_extra_function", "generator_id": "mx_minefield" },
 "min_max_zlevel": [ 0, 0 ],
 "sym": "M",
 "color": "red",
 "autonote": true,
 "flags": [ "MAN_MADE" ]
 }

```

* generator

（可选）一个对象，定义该额外项应如何生成以及生成什么

* min\_max\_zlevel

（可选）一对整数，定义此额外项可以在其中生成的最小和最大zlevel。默认为none（可以在任何级别生成）。

* sym

（可选）设置一个地图标记，并显示此参数所指示的符合，默认为无符号

* color

（可选）标识地图额外标记的符号的颜色，默认为白色

* autonote

（可选）是否在地图标记上自动标记此额外内容，默认为false

* flags

（可选）标识此额外项的标志列表。这些标志可以在overmap\_feature\_flag\_settings中列出，以添加黑名单或白名单地图

发电机可以使用以下三种方法之一：

* map\_extra\_function

generator\_id指向一个内置函数以生成额外的。有关当前列表，请参见map\_extras.pp中的内置函数映射

* mapgen

generator\_id指向mapgen定义中的om\_terrain字符串

* update\_mapgen

generator\_id指向mapgen定义中的update\_mapgen\_id字符串

### mx\_science

mx\_science地图额外产生了科学家的尸体以及一些敌人实体，地图额外定义如下：

```
 {
 "id": "mx_science",
 "type": "map_extra",
 "name": { "str": "Scientists" },
 "description": "Several corpses of scientists are here.",
 "generator": { "generator_method": "update_mapgen", "generator_id": "mx_science" },
 "min_max_zlevel": [ -5, 0 ],
 "sym": "s",
 "color": "light_red",
 "autonote": true
 }

```

在这种情况下，generator\_id指向mapgen定义，该定义确定将在该位置生成哪些对象或结构：

```
 {
 "type": "mapgen",
 "method": "json",
 "update_mapgen_id": "mx_science",
 "object": {
   "rows": [
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "-----------1----------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "----------------------  ",
     "                        ",
     "                        "
   ],
   "monsters": {
     " ": { "monster": "GROUP_NETHER_CAPTURED", "chance": 1, "density": 0.0001 },
     "-": { "monster": "GROUP_NETHER_CAPTURED", "chance": 1, "density": 0.0001 }
   },
   "nested": {
     "-": { "chunks": [ [ "corpse_blood_gibs_science_3x3", 1 ], [ "null", 150 ] ] },
     "1": { "chunks": [ "corpse_blood_gibs_science_3x3" ] }
   }
 }
 }

```

嵌套块定义了可能产生的项和字段：

```
 {
 "type": "mapgen",
 "method": "json",
 "nested_mapgen_id": "corpse_blood_gibs_science_3x3",
 "object": {
   "mapgensize": [ 3, 3 ],
   "place_items": [ { "item": "map_extra_science", "x": [ 0, 2 ], "y": [ 0, 2 ], "chance": 100 } ],
   "place_fields": [ { "field": "fd_blood", "x": [ 0, 2 ], "y": [ 0, 2 ] }, { "field": "fd_gibs_flesh", "x": [ 0, 2 ], "y": [ 0, 2 ] } ]
 }
 }

```

为了使额外的地图可用于生成，需要为其创建一个或多个region\_settings条目：

```
 {
 "type": "region_settings",
 "id": "default",
 ...
 "map_extras": {
   "forest": {
     "chance": 20,
     "extras": {
       "mx_helicopter": 1,
       "mx_military": 8,
       "mx_science": 20,
       "mx_collegekids": 25,
       ...
     }
   }
 }
 }

```

## overmap

~~又是一千多行上十条条目哈哈哈哈我和我的翻译机根本停不下来哈哈哈哈~~

当您单击[m]（或使用任何非点击[m]键的方式向游戏传输打开大地图的指令）时，大地图上所显示的便是overmap（覆盖贴图）。

它看起来有点像这个：

```
 ...>│<......................│..............P.FFFF├─FF...
 ..┌─┼─┐.....................│..............FFFFF┌┘FFFF..
 ..│>│^│.....................│..............FF┌─┬┘FFFFF.F
 ──┘...└──┐..............>│<.│..............F┌┘F│FFFFFFF─
 .........└──┐........vvO>│v.│............FF┌┘FF│FFFFFFFF
 ............└┐.......─┬──┼─>│<........┌─T──┘FFF└┐FFFFFFF
 .............│.......>│<$│S.│<.......┌┘..FFFFFFF│FFF┌─┐F
 ..O.........┌┴──┐....v│gF│O.│<v......│...FFFFFF┌┘F.F│F└─
.OOOOO.....─┘...└─────┼──┼──┼────────┤....FFFFF│FF..│FFF
 .O.O.....dddd.......^p│^>│OO│<^......└─┐FFFFFFF├────┴─FF
 .........dddd........>│tt│<>│..........│FFF..FF│FFFFF.FF
 .........dddd......┌──┘tT├──...........│FFF..F┌┘FFFFFFFF
 .........dddd......│....>│^^..H........└┐...FF│FFFFFFFFF
 ..................┌┘.....│<.............└─┐FF┌┘FFFFFFFFF
 ..................│......│................│FF│FFFFFFFFFF
 .................┌┘......│................│F┌┘FFFFFFFFFF
 ...FFF...........│......┌┘...............┌┘.│FFFFFFFFFFF
 FFFFFF...........│.....┌┘................│FF│FFFFFFFFFFF
 FFFFFF..FFFF.....│.....B..........─┐.....│┌─┘F..FFFFFFFF

```

想必老玩家一眼就能看出这是一个城市，森林包围了整座城市，林间有些小径，左边有个弹坑

在overmap生成后的ASCII画卷中，overmap是数据和特征的集合，这些数据和特征在比玩家直接与之交互的本地地图更抽象的层次上定义了游戏世界中各个建筑与地形的位置，为本地地图生成提供了必要的显示。

举个例子，overmap告诉游戏：

* 哪是你家
* 哪是房子
* 哪是城市
* 哪是道路
* 这些是什么类型的建筑

但它不能告诉游戏：

* 这些地形长啥样
* 地形建筑详细剖析
* 有哪些物品在建筑里面

因为这些是mapgen要做的

有时，将overmap视为游戏世界的轮廓是有用的，然后在玩家探索时将其填充，本文档的其余部分将讨论如何创建大纲。

### 生成覆盖贴图

生成overmap按以下函数顺序进行（请参见overmap.cpp中的generate::overmap）：

1. populate\_connections\_out\_from\_neighbors( north, east, south, west );
2. place\_rivers( north, east, south, west );
3. place\_lakes();
4. place\_forests();
5. place\_swamps();
6. place\_ravines();
7. place\_cities();
8. place\_forest\_trails();
9. place\_roads( north, east, south, west );
10. place\_specials( enabled\_specials );
11. place\_forest\_trailheads();
12. polish\_river();
13. place\_mongroups();
14. place\_radios();

如相关章节所述，这会对overmap特殊生成产生一些影响。

#### overmap\_terrain

overmap的基本单元是overmap\_terrain，它定义了用于表示overmap上的单个位置的id、名称、符号、颜色（以及更多信息，但我们将介绍），一个大地图宽180个overmap，高180个overmap地形，深21个overmap地形（这些是z级）。

在这个overmap的示例片段中，每个角色对应于overmap中引用给定覆盖地图地形的一个条目：

```
 .v>│......FFF│FF
 ──>│<....FFFF│FF
 <.>│<...FFFFF│FF
 O.v│vv.vvv┌──┘FF
 ───┼──────┘.FFFF
 F^^|^^^.^..F.FFF

```

例如，F是一个森林，其定义如下：

```
 {
   "type": "overmap_terrain",
   "id": "forest",
   "name": "forest",
   "sym": "F",
   "color": "green"
 }

```

而^是一个定义如下的房子：

```
 {
   "type": "overmap_terrain",
   "id": "house",
   "name": "house",
   "sym": "^",
   "color": "light_green"
 }

```

需要注意的是，对于覆盖地图中的每个覆盖地图地形的使用，都会引用一个单独的覆盖地图地形定义——如果我们要将森林的颜色从绿色更改为红色，则覆盖地图中每个森林都将是红色。

#### 覆盖地图\_特殊/城市建筑

overmap的下一个重要概念是overmap\_special和city\_building。这些类型在结构上相似，是一种机制，通过该机制，可以将多个覆盖地图地形收集到一个概念实体中，以放置在覆盖地图上。如果你想拥有一座庞大的豪宅、一栋两层楼的房子、一个大池塘，或者在一家不起眼的书店下面建一个秘密地下室，你需要使用一个面积过大的专门建筑或城市建筑。

这些类型实际上是构成它们的超地图地形的列表，这些超地图地形相对于彼此的位置，以及用于驱动超地图特殊/城市建筑的位置的一些数据（例如，离城市有多远，是否应连接到道路，是否可以放置在森林/田野/河流中等）。

注销或迁移一个overmap地形映射时，应在新的overmap\_special\_migration中定义id，通常在data/json/vovermap/vovermap\_sspecial/vovermap\_special\_mmigration.json中定义，如下所示：

```
 {
 "type": "overmap_special_migration",
 "id": "Military Bunker",
 "new_id": "military_bunker"
 }

```

已删除（而不仅仅是重命名）的特殊项应该有一个空的new\_id，或者干脆忽略new\_id字段。

#### overmap的连接

说到道路，线性特征（如道路、下水道、地铁、铁路和森林步道）都是通过重叠地形属性和另一种称为overmap\_connection的类型的组合来管理的。

overmap连接有效的定义了可以在其上进行给定连接的过映射地形类型、进行该连接的“cost”以及进行连接时要放置的地形类型。例如，这就是我们可以说的：

* 道路可以设置在田野、森林、沼泽和河流上
* 田野优于森林，森林优于沼泽，沼泽优于河流
* 一条道路要想穿越河流就必需要有一座桥

然后将使用overmap\_connection数据创建连接两个点的线性道路特征，并应用先前定义的规则。

#### overmap地点

我们之前已经提到过定义有效的覆盖地图地形类型来放置覆盖地图专用、城市建筑和覆盖地图连接，但需要澄清的是，这些地形类型实际上利用了另一种称为overmap\_location的类型，而不是直接引用overmap\_terrain值。

简单地说，overmap\_location只是overmap\_terrain值的命名集合。

例如，这里有两个简单的定义：

```
 { "type": "overmap_location", "id": "forest", "terrains": ["forest"] }, { "type": "overmap_location", "id": "wilderness", "terrains": ["forest", "field"] }

```

它们的价值在于，它们允许给定的覆盖地图地形属于多个不同的位置，并提供一个间接级别，以便在添加新的覆盖地图（或删除现有的覆盖地图）时，只需更改相关的覆盖地图位置条目，而不必更改需要这些组的每个覆盖地图连接、覆盖地图专用和城市建筑。

例如，添加新的森林覆盖地图地形forest\_thick后，我们只需按如下方式更新这些定义：

```
 {
   "type": "overmap_location",
   "id": "forest",
   "terrains": ["forest", "forest_thick"]
 },
 {
   "type": "overmap_location",
   "id": "wilderness",
   "terrains": ["forest", "forest_thick", "field"]
 }

```

### overmap地形

#### 旋转

如果覆盖地图地形可以旋转（即它没有NO\_ROTATE标志），那么当游戏从JSON加载定义时，它将自动创建旋转的定义，并在此处定义的id后面加上\_north、\_east、\_south或\_west。如果在overmap\_special或city\_building定义中使用了overmap地形，则这一点尤其重要，因为如果允许这些地形旋转，则需要为引用的overmap地形指定特定的旋转（例如，所有地形的\_north版本）。

#### 属性

* type

json对象的类型，这里必须是“overmap\_terrain”

* id

唯一ID

* name

游戏中显示的位置的名称。

* sym

绘制位置时使用的符号，如“F”（也可以使用ASCII值，如70）。

* color

这个地形的颜色，详见基础模组编写中的“color”条目

* looks\_like

要用于图形平铺的另一个覆盖贴图地形的Id（如果没有）。

* connect\_group

指定如果tileset希望，此覆盖地图地形可以图形方式连接到其邻居。它将连接到具有相同connect\_group的任何其他覆盖地图地形。

* see\_cost

影响玩家的视野，数值越高，处在此地形时的视野越差。

* travel\_cost

影响寻路成本，值越高，越难通过（参考：森林=10）

* extras

在region\_settings中对名为map\_extras的引用定义了可以应用哪些额外的地图。

* mondensity

加上相邻过地图地形的值，以影响此处繁殖的怪物密度。

* spawns

在mapgen添加一次生成，怪物群体，百分比几率，人口范围（最小/最大）。

* flags

请参见JSON\_FLAGS中的Overmap地形。

* mapgen

指定C++mapgen函数。不要这样做——使用JSON。

* mapgen\_straight

为线性特征变量指定C++mapgen函数。首选JSON。

* mapgen\_curved

为线性特征变量指定C++mapgen函数。首选JSON。

* mapgen\_end

为线性特征变量指定C++mapgen函数。首选JSON。

* mapgen\_tee

为线性特征变量指定C++mapgen函数。首选JSON。

* mapgen\_four\_way

为线性特征变量指定C++mapgen函数。首选JSON。

* eoc

提供effect\_on\_condition id或内联effect\_or\_condition。将测试eoc的状况，以确定是否可以放置特殊物品。放置特殊物品时，将运行eoc的效果。请参见effect\_on\_condition.md（官方github没这个文档，我琢磨半天没搞懂）。

#### 例子

一个真正的overmap\_terrain不会同时定义所有这些，但为了提供一个详尽的示例。。。

```
 {
   "type": "overmap_terrain",
   "id": "field",
   "name": "field",
   "sym": ".",
   "color": "brown",
   "looks_like": "forest",
   "see_cost": 2,
   "extras": "field",
   "mondensity": 2,
   "spawns": { "group": "GROUP_FOREST", "population": [ 0, 1 ], "chance": 13 },
   "flags": [ "NO_ROTATE" ],
   "mapgen": [ { "method": "builtin", "name": "bridge" } ],
   "mapgen_straight": [ { "method": "builtin", "name": "road_straight" } ],
   "mapgen_curved": [ { "method": "builtin", "name": "road_curved" } ],
   "mapgen_end": [ { "method": "builtin", "name": "road_end" } ],
   "mapgen_tee": [ { "method": "builtin", "name": "road_tee" } ],
   "mapgen_four_way": [ { "method": "builtin", "name": "road_four_way" } ],
   "eoc": {
     "id": "EOC_REFUGEE_CENTER_GENERATE",
     "condition": { "compare_int": [ { "global_val": "var", "var_name": "refugee_centers", "default": 0 }, "<", { "const": 1 } ] },
     "effect": [ { "arithmetic": [ { "global_val": "var", "var_name": "refugee_centers" }, "++" ] } ]
   }
 }

```

### 特殊overmap

超地图专用是在城市生成过程完成后放置在超地图中的实体——它们是城市建筑类型的“非城市”对应物。它们通常由多个超地图地形组成（尽管并非总是如此），可能具有超地图连接（例如道路、下水道、地铁），并且具有JSON定义的规则来指导它们的放置。

#### 特殊安置

在过映射生成期间，可以放置过映射特殊的扇区数量有限，每个扇区都是边长等于OMSPEC\_FREQ的正方形（在omdata.h中定义；在写入OMSPEC\_FEQ=15时，意味着每个过映射有144个扇区用于放置特殊）。在overmap生成开始时，将构建一个合格的地图特辑列表（overmap\_special\_batch）。接下来，选择一个自由区，放置一个特殊的。将该扇区中的随机点与来自特殊批次的随机特殊点的随机旋转进行检查，以查看其是否可以放置在那里。如果没有，扇区中的一个新随机点将与一个新的特殊点进行检查，依此类推，直到滚动到一个有效的产卵。

#### 固定与可变特殊

overmap special有两种类型：固定和可变。固定的过映射特殊件具有固定的定义布局，可以跨越多个OMT，并且可以旋转（见下文），但始终看起来基本相同。

可变的超地图特色具有更灵活的布局。它们是根据一组超地图地形以及它们可以组合在一起的方式来定义的，就像一个拼图游戏，其中各个块可以以多种方式组合在一起。这可以用来形成更有机的形状，比如巨型蚂蚁在地下挖掘的隧道，或者翅膀和延伸部分不匹配的大型建筑。

可变特殊件需要更加小心地设计，以便它们能够可靠地放置而不会出错。

#### 旋转

一般来说，最好将您的二次贴图特效定义为允许旋转——这将在游戏世界中提供多样性，并在尝试放置二次贴图专用时允许更多可能的有效位置。旋转覆盖地图特殊地形和旋转构成该特殊地形的底层覆盖地图地形之间的关系的结果是，覆盖地图特殊区域应引用相关覆盖地图地形的特定旋转版本——通常，这是\_north旋转，因为它对应于定义JSON对于mapgen的方式。

#### 连接

超高压专用电缆可以连接到道路、地铁或下水道网络。指定连接点会导致从最近的匹配地形自动生成适当的连接，除非将“existing”设置为true。

existing设置为true的连接用于测试二次映射特殊放置的有效性。与正常连接点不同，这些连接点不必参考道路/隧道地形类型。它们不会生成新的地形，甚至可能会被overmap特殊地形覆盖。然而，由于overmap特殊算法考虑了每一个overmap的有限数量的随机位置，因此使用以罕见地形为目标的existing连接大大降低了特殊生成的机会。

#### 出现次数（默认）

出现次数是设定特殊情况的基线稀有度的方法。该字段的行为方式有两种：默认情况下，它设置每个二次overmap特殊项的最小和最大出现次数。目前，所有overmap特殊值的最小值为0，以防止overmap彼此过于相似。此外，没有最大出现次数为1的特殊情况。这一点很重要，因为由于代码的一些古怪之处，每个普通特殊码在每个重叠的overmap中至少放置一次的几率非常高（最明显的是，特殊码的数量仅略多于每个重叠overmap的插入数量，放置失败的特殊码不会被取消资格，可以再次滚动，并且放置会重复直到所有扇区都被占用）。对于不常见的特殊情况，不足以保证每次过多地图出现一次以上，请使用“UNIQUE”标志。对于每个世界只能有一个实例的特殊情况，请使用“GLOBALLY\_UNIQUE”。

#### 发生次数( UNIQUE, GLOBALLY\_UNIQUE )

当特殊项具有“UNIQUE”或“GLOBALLY\_UNIQUE”标志时，而不是定义放置的最小和最大数量。occurrences字段定义特殊项被包含在任何一个给定的overmap地图中的机会。在任何放置掷骰之前，具有此标志的所有特殊都必须在x\_in\_y（第一个值，第二个值）掷骰中成功，以包含在当前生成的overmap的overmap\_special\_batch中；任何未通过本次掷骰的特殊游戏都不会被考虑放置。目前，所有UNIQUE特辑都使用[x，100]出现次数-百分比-以便于理解，但这不是必需的。

#### 位置

overmap地图专用有两种机制，用于指定其可能放置的有效位置（overmap\_location）。overmap地图中的每个条目都可能指定了有效位置，如果在不同类型的地形上允许使用专用的不同部分（例如，码头应该有一部分在岸上，一部分在水中），则这一点非常有用。如果所有值都相同，则可以使用顶级位置键为整个特殊项指定位置。单个条目的值优先于顶级值，因此可以定义顶级值，然后仅为不同的单个条目指定。

#### 城市距离和大小

在生成新的超地图期间，将在放置特殊地形之前生成城市及其连接道路。每个城市在生成的时候都被分配了一个规模，并将作为一个单一的十字路口开始其生活。城市距离字段指定了从城市半径边缘（而不是从城市中心）放置特殊对象的最小和最大距离。城市规模和城市距离要求都只针对“最近”的城市进行检查，从最开始生成的十字路口开始测量。

#### 属性

* type

此值必须是"overmap\_special"

* id

该对象的唯一id

* subtype

“fixed”或“mutable”。如果未指定，则默认为“fixed”。这表明它是否固定或可变。

* locations

可以放置特殊对象的overmap\_location ID列表。

* city\_distance

距可能放置特殊物品的城市边缘的最小/最大距离。使用-1表示无边界。

* city\_sizes

特殊对象可能靠近的城市的最小/最大城市大小。使用-1表示无边界。

* occurrences

放置特殊对象时出现的最小/最大次数。如果设置了UNIQUE标志，则变为Y中的X。

* flags

请参见JSON\_FLAGS中的Overmap specials。

* rotate

是否可以旋转。如果未指定，则为True。

根据子类型，还有其他相关字段：

##### 固定的（fixed）特殊overmap的其它字段

* overmaps

overmap地图地形及其在特殊区域内的相对[x，y，z]位置列表。

* connections

特殊范围内的overmap连接及其相对[x，y，z]位置列表。

##### 可变的（mutable）过映射特殊的其他字段

* check\_for\_locations

定义初始放置必须存在的位置的对[[x，y，z]，[locations，…]]的列表。

* check\_for\_locations\_area

除了显式check\_for\_locations对之外，还要考虑的check\_for\_locations区域对象列表。

* overmaps

各种过剩的定义以及它们如何相互结合。

* root

将从中生长的可变的overmap覆盖的初始overmap覆盖。

* phase

关于如何从根OMT中生长overmap special的规范。

#### fixed固定overmap特殊示例

```
[
 {
   "type": "overmap_special",
   "id": "campground",
   "overmaps": [
     { "point": [ 0, 0, 0 ], "overmap": "campground_1a_north", "locations": [ "forest_edge" ] },
     { "point": [ 1, 0, 0 ], "overmap": "campground_1b_north" },
     { "point": [ 0, 1, 0 ], "overmap": "campground_2a_north" },
     { "point": [ 1, 1, 0 ], "overmap": "campground_2b_north" }
   ],
   "connections": [ { "point": [ 1, -1, 0 ], "terrain": "road", "connection": "local_road", "from": [ 1, 0, 0 ] } ],
   "locations": [ "forest" ],
   "city_distance": [ 10, -1 ],
   "city_sizes": [ 3, 12 ],
   "occurrences": [ 0, 5 ],
   "flags": [ "CLASSIC" ],
   "rotate" : true
 }
]

```

#### 特殊fixed overmap属性

* point

[x，y，z]表示特殊区域内的覆盖地图地形。

* overmap

要放置在该位置的overmap\_terrain的Id。

* locations

可以放置此覆盖地图地形的覆盖地图位置ID列表。

#### 连接

* point

连接终点的[x，y，z]。不能重叠特殊地形的过映射地形条目。

* terrain

最终会走向连接。使用道路、地铁、下水道等。

* connection

要生成的overmap\_connection的Id。目前是可选的，但您应该明确指定它。

* from

特殊项中的可选点[x，y，z]将被视为连接的原点。

* existing

布尔值，默认为false。如果特殊需要预先存在的地形来生成。

#### 示例可变特殊

```
 [
 {
   "type": "overmap_special",
   "id": "anthill",
   "subtype": "mutable",
   "locations": [ "subterranean_empty" ],
   "city_distance": [ 25, -1 ],
   "city_sizes": [ 0, 20 ],
   "occurrences": [ 0, 1 ],
   "flags": [ "CLASSIC", "WILDERNESS" ],
   "//example": "The following check_for_locations_area field is superfluous in this example, and serves as a proof of concept",
   "check_for_locations_area": [
     { "type": [ "subterranean_empty" ], "from": [ -1, -1, -1 ], "to": [ 1, 1, -1 ] }
   ],
   "check_for_locations": [
     [ [ 0, 0, 0 ], [ "land" ] ],
     [ [ 0, 0, -1 ], [ "subterranean_empty" ] ],
     [ [ 1, 0, -1 ], [ "subterranean_empty" ] ],
     [ [ 0, 1, -1 ], [ "subterranean_empty" ] ],
     [ [ -1, 0, -1 ], [ "subterranean_empty" ] ],
     [ [ 0, -1, -1 ], [ "subterranean_empty" ] ]
   ],
   "joins": [ "surface_to_tunnel", "tunnel_to_tunnel" ],
   "overmaps": {
     "surface": { "overmap": "anthill", "below": "surface_to_tunnel", "locations": [ "land" ] },
     "below_entrance": {
       "overmap": "ants_nesw",
       "above": "surface_to_tunnel",
       "north": "tunnel_to_tunnel",
       "east": "tunnel_to_tunnel",
       "south": "tunnel_to_tunnel",
       "west": "tunnel_to_tunnel"
     },
     "crossroads": {
       "overmap": "ants_nesw",
       "north": "tunnel_to_tunnel",
       "east": "tunnel_to_tunnel",
       "south": "tunnel_to_tunnel",
       "west": "tunnel_to_tunnel"
     },
     "tee": { "overmap": "ants_nes", "north": "tunnel_to_tunnel", "east": "tunnel_to_tunnel", "south": "tunnel_to_tunnel" },
     "straight_tunnel": { "overmap": "ants_ns", "north": "tunnel_to_tunnel", "south": "tunnel_to_tunnel" },
     "corner": { "overmap": "ants_ne", "north": "tunnel_to_tunnel", "east": "tunnel_to_tunnel" },
     "dead_end": { "overmap": "ants_end_south", "north": "tunnel_to_tunnel" },
     "queen": { "overmap": "ants_queen", "north": "tunnel_to_tunnel" },
     "larvae": { "overmap": "ants_larvae", "north": "tunnel_to_tunnel" },
     "food": { "overmap": "ants_food", "north": "tunnel_to_tunnel" }
   },
   "root": "surface",
   "phases": [
     [ { "overmap": "below_entrance", "max": 1 } ],
     [
       { "overmap": "straight_tunnel", "max": 20 },
       { "overmap": "corner", "max": { "poisson": 5 } },
       { "overmap": "tee", "max": 10 }
     ],
     [ { "overmap": "queen", "max": 1 } ],
     [ { "overmap": "food", "max": 5 }, { "overmap": "larvae", "max": 5 } ],
     [
       { "overmap": "dead_end", "weight": 2000 },
       { "overmap": "straight_tunnel", "weight": 100 },
       { "overmap": "corner", "weight": 100 },
       { "overmap": "tee", "weight": 10 },
       { "overmap": "crossroads", "weight": 1 }
     ]
   ]
 }
 ]

```

### 如何放置可变（mutable）特殊项

#### Overmaps与joins连接

一个可变的特殊对象有一组overmap，用于定义用于构建它的OMT，以及定义允许它们彼此连接的方式的联接。每个overmap可以为其每个边指定一个连接（上下四个基本方向）。这些连接必须与该方向上相邻二次覆盖的相反连接相匹配。

在上面的示例中，我们看到surface overmap指定了“below”：“surface\_to\_tunnel”，这意味着它下面的连接必须是surface\_t\_to\_tunel。因此，下面的overmap必须指定“above”：“surface\_to\_tunnel”。只有below\_entrance的overmap才能做到这一点，因此我们知道overmap必须放置在surface overmap的下面。

overmap始终可以旋转，因此北向约束可以对应于其他方向。因此，上面的dead\_end overmap可以表示任何方向上的dead\_end隧道，但重要的是，所选的OMT ants\_end\_south与生成的地图的北向连接一致。

overmap还可以指定连接。例如，overmap可以定义为：

```
"where_road_connects": {
 "overmap": "road_end_north",
 "west": "parking_lot_to_road",
 "connections": { "north": { "connection": "local_road" } }
}

```

一旦可变特殊放置完成，将从该overmap的北边缘构建local\_road连接（同样，“north”是一个相对术语，将随着overmap的旋转而旋转），其方式与为固定特殊对象构建连接的方式相同可变的特殊项不支持现有的“Existing”。

#### 布局阶段

在定义了所有连接和重叠后，特殊的布局方式由根和相位给出。

root指定首先放置在该特殊对象原点处的overmap。

然后，阶段列出了用于放置更多过剩的增长阶段。这些阶段严格按顺序处理。

每个阶段都是规则列表。每个规则指定一个overmap和一个整数最大值和/或权重。

权重必须始终是一个简单的整数，但max也可以是定义整数上概率分布的对象。每次生成特殊项时，都会从该分布中采样一个值。目前只支持泊松分布，通过诸如{“Poisson”:5}的对象指定，其中5将是分布的平均值（λ）。

在每个阶段，游戏都会从现有的过匹配中寻找未满足的连接，并尝试从其规则中可用的连接中找到一个过匹配以满足该连接。在定义此特殊连接的列表中，优先考虑最先列出的连接，但如果存在相同（最高优先级）id的多个连接，则随机选择一个。

首先对规则进行过滤，使其仅包含能够满足特定位置的连接的规则，然后从过滤列表中进行加权选择。权重由规则中指定的最大值和最小值给出。max和weight之间的区别在于，每次使用规则时，max都会减一。因此，它限制了可以选择该规则的次数。只指定权重的规则可以选择任意次数。

如果当前阶段中没有规则能够满足特定位置的连接，则将该位置放在一旁，以便在以后的阶段中再次尝试。

一旦所有连接都得到满足或被搁置，该阶段结束，生成过程继续到下一阶段。

如果所有阶段都已完成且未满足连接，则这将被视为错误，并将显示一个debugmsg，其中包含更多详细信息。

#### chunks（块）

阶段中的放置规则可以指定要放置在特定配置中的多个overmap。如果您想放置比单个OMT更大的功能，这很有用。以下是microlab的示例：

```
{
 "name": "subway_chunk_at_-2",
 "chunk": [
   { "overmap": "microlab_sub_entry", "pos": [ 0, 0, 0 ], "rot": "north" },
   { "overmap": "microlab_sub_station", "pos": [ 0, -1, 0 ] },
   { "overmap": "microlab_subway", "pos": [ 0, -2, 0 ] }
 ],
 "max": 1
}

```

chunks的“namr”仅用于在出现错误时显示调试消息使用。“max”和“weight”按上述方式处理。

新功能是“chunks”，它指定了一个overmap列表及其相对位置和旋转。overmaps是从为这个特殊的定义中选取的。“north”的旋转是默认值，因此指定它没有任何效果，但这里包含了它来演示语法。

位置和旋转是相对的。该chunks可以放置在任何偏移和旋转位置，只要所有的overmaps像固定的一体一样一起移动和旋转。

#### 避免放置错误的技巧

为了帮助避免这些错误，可变特殊放置的一些附加功能可以帮助您。

* check\_for\_locations

check\_for\_locations定义了在尝试放置特殊项之前检查的额外约束的列表。每个约束是一对位置（相对于根）和一组位置。每个位置的现有OMT必须位于给定位置之一，否则尝试放置将被中止。

check\_for\_locations约束确保below\_entrance overmap可以放置在root之下，并且所有四个主要相邻OMT都是subtrangen\_empty，这是添加满足below\_eentrance的其他四个连接的任何其他overmap所需的。

* check\_for\_locations\_area

check\_for\_locations\_area定义了除check\_for\_locations约束之外要考虑的额外矩形约束区域的列表。它是一个定义单个位置的对象数组，以及定义约束的方形区域的from和to三点，如下所示：

```
 "check_for_locations_area": [
 { "type": [ "subterranean_empty" ], "from": [ -1, -1, -1 ], "to": [ 1, 1, -1 ] }
 ],

```

对于以上内容，check\_For\_locations\_area字段相当于手动向check\_For\_locations数组添加以下约束：

```
 [ [ 0, 0, -1 ], [ "subterranean_empty" ] ],
 [ [ 1, 0, -1 ], [ "subterranean_empty" ] ],
 [ [ 0, 1, -1 ], [ "subterranean_empty" ] ],
 [ [ -1, 0, -1 ], [ "subterranean_empty" ] ],
 [ [ 0, -1, -1 ], [ "subterranean_empty" ] ],
 [ [ 1, 1, -1 ], [ "subterranean_empty" ] ],
 [ [ 1, -1, -1 ], [ "subterranean_empty" ] ],
 [ [ -1, 1, -1 ], [ "subterranean_empty" ] ],
 [ [ -1, -1, -1 ], [ "subterranean_empty" ] ]

```

示例mutable special中的check\_for\_locations\_area字段是多余的，仅用于说明字段的语法。

请查看/json/vovermap/vovermap\_mutable/nether\_monster\_corpse.json，了解在一个真正的可变特殊平铺中该字段的应用程序。

* into\_locations

每个联接还具有关联的位置列表。这默认为特殊连接的位置，但可以为特定连接重写，如下所示：

```
 "joins": [
 { "id": "surface_to_surface", "into_locations": [ "land" ] },
 "tunnel_to_tunnel"
 ]

```

对于要在满足未解析连接时放置的overmap，仅满足与特定位置相邻的现有连接是不够的。它所拥有的任何剩余连接都必须指向地形与该连接位置一致的OMT。

对于上面的anthill示例的特定情况，我们可以看到这两个添加是如何确保放置总是成功的，并且没有出错的连接。

接下来的几个浇筑阶段将尝试铺设各种隧道。连接约束将确保未满足的连接（隧道开口端）始终指向标签为subterranean\_empty的OMT。

##### 确保在最后阶段完全覆盖

在最后阶段，我们有五个不同的规则，旨在限制任何错误的插入，而不会进一步增加anthill further。重要的是，其overmaps具有较少联接的规则获得更高的权重。在正常情况下，每个未满足的联接都将使用dead\_end简单地关闭。然而，我们还必须考虑到两个未满足的连接指向同一OMT的可能性，在这种情况下，dead\_end将不适合（并将被过滤掉），但direct\_tunnel或corner将适合，并且其中一个可能会被选择，因为它们具有最高的权重。我们不希望选择发球台（尽管它可能很合适），因为这会导致新的不满意的连接，并进一步扩大隧道。但在这种情况下，如果偶尔选择发球台，也不是什么大问题；新的联接很可能只是使用dead\_end来满足。

在设计自己的可变的overmap特殊功能时，您必须仔细考虑这些排列，以确保在最后阶段结束时满足所有连接。

#### 可选联接

与其在最后阶段设计大量规则来满足所有可能的情况，不如在某些情况下使用可选联接来简化这一过程。此功能也可以用于其他阶段。
在可变特殊中指定与二次映射关联的联接时，可以使用类型进行详细说明，如Crater二次映射特殊中的此示例：

```
 "overmaps": {
 "crater_core": {
   "overmap": "crater_core",
   "north": "crater_to_crater",
   "east": "crater_to_crater",
   "south": "crater_to_crater",
   "west": "crater_to_crater"
 },
 "crater_edge": {
   "overmap": "crater",
   "north": "crater_to_crater",
   "east": { "id": "crater_to_crater", "type": "available" },
   "south": { "id": "crater_to_crater", "type": "available" },
   "west": { "id": "crater_to_crater", "type": "available" }
 }
 },

```

crater\_edge的定义在北方有一个强制连接，在其他主要方向有三个“可用”连接。“可用”联接的语义是，它不会被视为未解析联接，因此永远不会导致放置更多的重叠，但它可以在必要时满足特定瓦片中的其他联接，以允许满足现有的未解析联接。

overmap将始终以这样一种方式旋转，即满足尽可能多的强制联接，并保留可用联接指向当前不需要联接的其他方向。

因此，此crater\_edge二次映射可以满足crater special的任何未解析联接，而不会生成任何新的未解析联接。这使得在最后阶段完成特殊overmap连接的工作变得更加顺利。

#### 不对称联接

有时你想要两个不同的OMT连接，但不希望任何一个与自己连接。在这种情况下，您不希望在两者上使用相同的联接。相反，您可以定义两个连接，通过将其中一个指定为另一个的对立面，形成一对。

另一种可能出现这种情况的情况是，连接的两侧需要不同的位置约束。例如，在anthill further中，地表和地下成分需要不同的位置。我们可以通过使表面和隧道之间的连接不对称来改进其连接的定义，如下所示：

```
 "joins": [
 { "id": "surface_to_tunnel", "opposite": "tunnel_to_surface" },
 { "id": "tunnel_to_surface", "opposite": "surface_to_tunnel", "into_locations": [ "land" ] },
 "tunnel_to_tunnel"
 ],

```

正如您所看到的，该tunnel\_to\_surface部分需要覆盖into\_locations的默认值，因为它指向另一个覆盖。

#### 替代连接

有时，您希望可变特别计划的下一阶段能够链接到 现有的未解析连接，而自身不生成的任何未解析连接 那种类型的。这有助于在新旧之间建立一条干净的分界线。

例如，这发生在microlab\_mutable特别的这个特别的有 一些结构化的hallwayOMTs被一群microlabOMTs. 走廊有hallway\_to\_microlab连接指向他们的侧面，所以我们 需要microlabOMT应具有microlab\_to\_hallway连接(与hallway\_to\_microlab)以便与它们相匹配。

但是，我们不希望microlabOMT需要更多 走廊到处都是，所以我们主要想让他们使用microlab\_to\_microlab我们如何才能满足这些明显冲突的需求而不 使许多不同的变体microlab每种都有不同数量的 连接类型？可选连接可以帮助我们实现这一点。

的定义microlabovermap可能如下所示：

```
 "microlab": {
 "overmap": "microlab_generic",
 "north": { "id": "microlab_to_microlab", "alternatives": [ "microlab_to_hallway" ] },
 "east": { "id": "microlab_to_microlab", "alternatives": [ "microlab_to_hallway" ] },
 "south": { "id": "microlab_to_microlab", "alternatives": [ "microlab_to_hallway" ] },
 "west": { "id": "microlab_to_microlab", "alternatives": [ "microlab_to_hallway" ] }
 },

```

这允许它与已经放置在overmap上的走廊连接， 但新的未解析连接只会匹配更多microlabs。

##### 测试您的新的可变特殊功能

如果您想彻底测试您的可变特异程序是否存在放置错误，以及 如果您处于编译游戏的位置，那么一个简单的方法是使用 中的现有测试tests/overmap\_test.cpp.

在该文件中查找TEST\_CASE( "mutable\_overmap\_placement".开始时 该函数有一个测试尝试的可变特异id列表。 产卵。将其中一个替换为您的新特殊产品的ID，重新编译并运行 测试。

测试将尝试放置您的特殊数千次，并且应该 找出放置可能失败的大多数方式。

#### 连接

联接定义可以是一个简单的字符串，它将是其ID。或者， 它可以是具有以下某些键的字典：

* id

要定义的联接的ID。

* opposite

连接的ID，该ID必须与相邻地形中的此ID相匹配。

* into\_locations

列表overmap\_location此连接可能指向的ID。

#### 可变特殊overmap

overmap是一个JSON字典。每个overmap必须具有一个id(本地到 (this special)，它是JSON字典键，然后是 值可以是：

* overmap

的IDovermap\_terrain放置在位置。

* locations

列表overmap\_location可以放置此覆盖地图地形的ID。如果未指定，则默认为locations特殊定义中的值。

* north

必须与该OMT北边缘对齐的连接

* east

必须与该OMT东边缘对齐的连接

* south

必须与该OMT的南边缘对齐的连接

* west

必须与该OMT西边缘对齐的连接

* above

join，必须将此链接到上面的OMT

* below

join，必须将此链接到下面的OMT

与方向关联的每个联接都可以是一个简单的字符串，将其解释为 join id。或者，它可以是具有以下键的JSON对象：

* id

此处使用的联接的ID。

* type

或者"mandatory"或"available"。默认值："mandatory".

* alternatives

可以使用的连接ID的列表，而不是下面列出的连接ID。id，但仅在放置此覆盖图时。由其放置创建的未解析联接将只是主联接id.

#### 生成规则

* overmap

IDovermap到地点。

* max

应使用此规则的最大次数。

* weight

选择此规则的权重。

其中之一max和weight必须指定。max将用作砝码 当weight未指定。

### 城市建筑

城市建筑是在城市生成过程中放置在总体图中的实体，“城市”是否对应于overmap\_special类型。城市建筑的定义是一个子集，这是一个特殊的overmap，因此这里不会详细重复。

#### 强制放置特殊Overmap/区域设置

城市建筑的数量限制不像特殊Overmap那么多，而且事实上 出现次数属性根本不适用。相反，城市建筑的布局中分配给城市建筑的频率。region\_settings.咨询region\_Settings.md了解更多详细信息。

* type

必须是"city\_building"。

* id

唯一ID。

* overmaps

如在overmap\_special，但有一个警告：所有点x和y值必须>=0。

* locations

如在overmap\_special.

* flags

如在overmap\_special.

* rotate

如在overmap\_special.

```
 [
 {
   "type": "city_building",
   "id": "zoo",
   "locations": [ "land" ],
   "overmaps": [
     { "point": [ 0, 0, 0 ], "overmap": "zoo_0_0_north" },
     { "point": [ 1, 0, 0 ], "overmap": "zoo_1_0_north" },
     { "point": [ 2, 0, 0 ], "overmap": "zoo_2_0_north" },
     { "point": [ 0, 1, 0 ], "overmap": "zoo_0_1_north" },
     { "point": [ 1, 1, 0 ], "overmap": "zoo_1_1_north" },
     { "point": [ 2, 1, 0 ], "overmap": "zoo_2_1_north" },
     { "point": [ 0, 2, 0 ], "overmap": "zoo_0_2_north" },
     { "point": [ 1, 2, 0 ], "overmap": "zoo_1_2_north" },
     { "point": [ 2, 2, 0 ], "overmap": "zoo_2_2_north" }
   ],
   "flags": [ "CLASSIC" ],
   "rotate" : true
 }
 ]

```

### overmap连接

#### 字段

* type

必须为“overmap\_connection”。

* id

唯一ID。

* subtypes

用于确定有效位置、地形成本和生成的覆盖地图地形的条目列表。

#### 样例

```
 [
 {
   "type": "overmap_connection",
   "id": "local_road",
   "subtypes": [
     { "terrain": "road", "locations": [ "field", "road" ] },
     { "terrain": "road", "locations": [ "forest_without_trail" ], "basic_cost": 20 },
     { "terrain": "road", "locations": [ "forest_trail" ], "basic_cost": 25 },
     { "terrain": "road", "locations": [ "swamp" ], "basic_cost": 40 },
     { "terrain": "road_nesw_manhole", "locations": [  ] },
     { "terrain": "bridge", "locations": [ "water" ], "basic_cost": 120 }
   ]
 },
 {
   "type": "overmap_connection",
   "id": "subway_tunnel",
   "subtypes": [ { "terrain": "subway", "locations": [ "subterranean_subway" ], "flags": [ "ORTHOGONAL" ] } ]
 }
 ]

```

#### 子类型

* terrain

overmap\_terrain放置位置匹配时放置locations.

* locations

列表overmap\_location此子类型适用的。可以为空；表示terrain按原样有效。

* basic\_cost

寻径路由时此子类型的开销。默认值为0。

* flags

看见Overmap connections在……内JSON\_FLAGS.md.

### overmap位置

#### 字段

* type

必须为“overmap\_location”。

* id

唯一ID。

* terrains

列表overmap\_terrain可以被认为是这个位置的一部分。

#### 样例

```
 [
 {
   "type": "overmap_location",
   "id": "wilderness",
   "terrains": [ "forest", "forest_thick", "field", "forest_trail" ]
 }
 ]

```

### 城市

城市类型的对象定义将出现在特定位置的overmap上的城市。请注意，如果至少定义了一个城市，则不会生成随机城市。

#### 字段

* id

城市ID。

* database\_id

Ma数据库中城市的ID。

* name

城市的名称。

* population

城市的原始人口。

* size

城市的规模。

* pos\_om

城市的位置(在大地图坐标中)。

* pos

城市的位置(在大地图地形坐标中)。

#### 示例

```
 {
 {
   "type": "city",
   "id": "35",
   "database_id": 35,
   "name": "BOSTON",
   "population": 617594,
   "size": 64,
   "pos_om": [ 46, 15 ],
   "pos": [ 57, 94 ]
 }
 }

```