模组:世界地图
← 目录
此页面解释如何编辑世界地图。世界地图是指游戏菜单中显示的小地图,而不是游戏地点的地图数据。欲编辑后者,参见模组:地图。另请参阅创建模组。
数据
概览
您可以通过编辑Data/WorldMap素材文件以编辑世界地图,包括但不限于:添加自定义地图、设置覆盖贴图、添加/编辑提示框、设置玩家图标等。
关于世界地图有三个主要概念(对照右图):
- 一个地区 (region) 是指世界的一大组成部分,它包含相应地图上的全部地点。例如,默认世界地图对应星露谷地区。
- 一个地图区域 (map area) 是一张世界地图的子集,可以酌情添加提示框、滚动文本、贴图、玩家定位图标等内容。
- 一个地图区域位置 (map area position) 对应于游戏内的地点以及地块坐标,以用于绘制地图。游戏使用地图区域位置来自动在世界地图上绘制玩家定位图标(定位图标适用于观察其他玩家在各个地点的行动等用途)。
在数据模型中:
- 每个条目都是一个地区;
- 每个条目的MapAreas为此地区的地图区域;
- 每个地图区域的WorldPositions字段为相应地图区域位置。
游戏会首先查找与当前地点匹配的第一个WorldPositions条目,然后认为您正处于此地区和地图区域中。若未找到,则默认为农场。
格式
Data/WorldMap数据素材为一个“字符串 → 数据模型”查询,其中:
- 键为此地区的唯一字符串ID。
- 值为包含如下字段的数据模型。
字段 | 效果 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
BaseTexture | (可选) 为地图绘制的基础贴图(若有)。会应用第一个匹配的贴图。如果地图区域也提供了自己的贴图,则会绘制在基础贴图之上。
此字段为包含如下字段的数据模型所组成的列表:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MapAreas | 绘制在BaseTexture顶层的区域。可在此添加提示框、滚动文本、覆盖贴图和玩家定位信息。
此字段为包含如下字段的数据模型所组成的列表:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MapNeighborIdAliases | (可选) 某些提示框ID的别名,可用于Tooltips下辖字段(如LeftNeighbor)。别名不能递归。
下面的代码会设置了Beach/FishShop_DefaultHours和Beach/FishShop_ExtendedHours的别名Beach/Fishshop。您可以直接在Neighbor字段中使用Beach/Fishshop,而不必每次都指定具体的提示框ID。 "MapNeighborIdAliases": {
"Beach/FishShop": "Beach/FishShop_DefaultHours, Beach/FishShop_ExtendedHours"
}
|
示例
下面的Content Patcher内容包为姜岛添加了一个新的世界地图。如果玩家解锁了海滩度假村,则会应用海滩度假村贴图。
{
"Format": "2.3.0",
"Changes": [
// add world map edits
{
"Action": "EditData",
"Target": "Data/WorldMap",
"Entries": {
"GingerIsland": {
"BaseTexture": [
{
"Id": "Default",
"Texture": "{{InternalAssetKey: assets/ginger-island.png}}"
}
],
"MapAreas": [
// the Island South (dock) area
{
// basic info for the area within the map
"Id": "IslandSouth",
"PixelArea": { "X": 105, "Y": 105, "Width": 231, "Height": 240 },
"ScrollText": "Dock", // example only, should usually be translated
// a tooltip shown when hovering over the area on the map
"Tooltips": [
{
"Id": "Dock",
"Text": "Dock" // example only, should usually be translated
}
],
// if the resort is unlocked, overlay a custom texture on top of the default Ginger Island map
"Textures": [
{
"Id": "Resort",
"Texture": "{{InternalAssetKey: assets/resort.png}}",
"Condition": "PLAYER_HAS_FLAG Any Island_Resort"
}
],
// the in-game locations that are part of this world map area
"WorldPositions": [
{
"LocationName": "IslandSouth"
}
]
}
]
}
}
}
]
}
实时定位
世界地图一般会实时显示玩家的位置。对于自定义地点,主要有三种方法。
自动定位(推荐)
如果实际地点和游戏地图显示的地点较为契合,游戏可以根据 Data/WorldMap 中的 PixelArea 和 LocationName 字段自动确定位置。例如,位于游戏中位置正中心的玩家将被绘制在所绘制地图区域的中心。
为此
- 截一张此地点的完整图片。
- 用Paint.NET或GIMP等图片编辑器打开此截图。
- 按需裁切,然后将尺寸调整为地图上此地点的尺寸。确保您使用的是"nearest neighbor"算法[1]。
- 酌情修改,以求美观。
这样就做好了!您可以将此图片作为该地点的世界地图贴图(存储在Data/WorldMap),这样游戏就可以自动在地图上定位玩家。当您使用此自动定位方式时,可以省略WorldPositions字段。
- ↑ 对于Paint. NET,将Rescale菜单中的Resampling选项设为Nearest Neighbor ;对于GIMP,将Interpolation设为None即可。
手动定位
如果地点的真实布局和地图上显示的有所出入,则可以在Data/WorldMap中使用WorldPositions字段来手动设置定位。这可能非常棘手,故不推荐。强烈推荐自动定位。
例如,在《星露谷物语 1.6》之前,深山的地图区域非常不写实(矿井和探险家公会紧挨着,没有湖心岛,公会南面没有山湖,等等):
在手动定位时,您可以通过TileArea和MapPixelArea字段添加任意数量的世界位置。其中,TileArea是指玩家真实的地块坐标,而MapPixelArea是指地图上显示的位置。当玩家位于 TileArea 内时,他们将被映射到对应的 MapPixelArea 内的相对位置。例如,如果玩家位于 TileArea 的正中心,那么他们将被绘制在 MapPixelArea 的中心。
参见下面的例子,您可以像这样将 1.6 之前的深山划分为多个区域(有关每个字段的信息,请参阅数据格式):
"WorldPositions": [
{
"Id": "Quarry",
"LocationName": "Mountain",
"TileArea": { "X": 95, "Y": 11, "Width": 36, "Height": 24 },
"ExtendedTileArea": { "X": 95, "Y": 0, "Width": 255, "Height": 255 },
"MapPixelArea": { "X": 236, "Y": 29, "Width": 28, "Height": 19 }
},
{
"Id": "Lake_Guild",
"LocationName": "Mountain",
"TileArea": { "X": 73, "Y": 5, "Width": 22, "Height": 30 },
"ExtendedTileArea": { "X": 73, "Y": 0, "Width": 22, "Height": 255 },
"MapPixelArea": { "X": 227, "Y": 29, "Width": 9, "Height": 19 }
},
{
"Id": "Lake_BetweenGuildAndMine",
"LocationName": "Mountain",
"TileArea": { "X": 57, "Y": 5, "Width": 16, "Height": 32 },
"ExtendedTileArea": { "X": 57, "Y": 0, "Width": 16, "Height": 255 },
"MapPixelArea": { "X": 224, "Y": 29, "Width": 3, "Height": 19 }
},
{
"Id": "Lake_Mine",
"LocationName": "Mountain",
"TileArea": { "X": 52, "Y": 5, "Width": 5, "Height": 30 },
"ExtendedTileArea": { "X": 52, "Y": 0, "Width": 5, "Height": 255 },
"MapPixelArea": { "X": 220, "Y": 29, "Width": 4, "Height": 19 }
},
{
"Id": "Lake_MineBridge",
"LocationName": "Mountain",
"TileArea": { "X": 44, "Y": 5, "Width": 8, "Height": 30 },
"ExtendedTileArea": { "X": 44, "Y": 0, "Width": 8, "Height": 255 },
"MapPixelArea": { "X": 210, "Y": 29, "Width": 10, "Height": 19 }
},
{
"Id": "West",
"LocationName": "Mountain",
"TileArea": { "X": 0, "Y": 5, "Width": 44, "Height": 30 },
"ExtendedTileArea": { "X": 0, "Y": 0, "Width": 44, "Height": 255 },
"MapPixelArea": { "X": 175, "Y": 29, "Width": 35, "Height": 19 }
},
{
"Id": "Default",
"LocationName": "Mountain"
}
]
下面是这些区域的直观示意图:
请注意,矿井和冒险者公会之间的区域实际上很宽,但在绘制的世界地图上却很窄。当玩家走过这部分区域时,他们的图标将在地图上缓慢地走过相应区域。
如果玩家在 TileArea 之外,但在 ExtendedTileArea(如果已设置)之内,他们的位置将被调整到 TileArea 内最近的位置。例如,请注意木匠店南面位置的底部并不属于红色区域。但它是该区域的ExtendedTileArea的一部分,因此在那里的玩家将被定位到世界地图上红色区域的底部。
固定位置
对于非常复杂的地点,可能无法在世界地图上实时定位(例如,因为绘制的世界地图非常不写实)。在这种情况下,您可以在世界地图上设置一个固定位置(或多个固定位置)。
请看下面的例子。它会根据玩家在镇上的真实位置,在世界地图的五个固定位置之一绘制玩家图标。TileArea指示玩家真实的地块坐标,而MapPixelArea则是在地图上绘制玩家图标的位置。请注意,在下面的代码中,后者始终是 1x1 像素,这意味着 TileArea 内的任何位置都对应世界地图上的同一个像素。最后一项没有 TileArea,这意味着它适用于所有与前一项不匹配的位置。
"WorldPositions": [
{
"Id": "East_NearJojaMart",
"LocationName": "Town",
"TileArea": { "X": 85, "Y": 0, "Width": 255, "Height": 68 },
"MapPixelArea": { "X": 225, "Y": 81, "Width": 1, "Height": 1 }
},
{
"Id": "East_NearMuseum",
"LocationName": "Town",
"TileArea": { "X": 81, "Y": 68, "Width": 255, "Height": 255 },
"MapPixelArea": { "X": 220, "Y": 108, "Width": 1, "Height": 1 }
},
{
"Id": "West_North",
"LocationName": "Town",
"TileArea": { "X": 0, "Y": 0, "Width": 85, "Height": 43 },
"MapPixelArea": { "X": 178, "Y": 64, "Width": 1, "Height": 1 }
},
{
"Id": "West_Center",
"LocationName": "Town",
"TileArea": { "X": 0, "Y": 43, "Width": 85, "Height": 33 },
"MapPixelArea": { "X": 175, "Y": 88, "Width": 1, "Height": 1 }
},
{
"Id": "West_South",
"LocationName": "Town",
"MapPixelArea": { "X": 182, "Y": 109, "Width": 0, "Height": 0 }
}
]
在C#中与世界地图交互
SMAPI模组(使用C#)可以调用游戏的StardewValley.WorldMaps.WorldMapManager类以与世界地图互动。
例如,您可以获取某地块坐标在世界地图上对应的像素位置:
MapAreaPosition mapAreaPosition = WorldMapManager.GetPositionData(location, tile);
if (mapAreaPosition != null)
return mapAreaPosition.GetMapPixelPosition(location, tile);
调试视图
您可以在 SMAPI 控制台窗口中运行 debug worldMapLines,以启用世界地图的调试视图。这将勾勒出地图区域(黑色)、地图区域位置(蓝色)和提示框(绿色):
您也可以自行指定要框起来的地图元素,例如debug worldMapLines areas positions tooltips。