维护提醒

BWIKI 全站将于 9 月 3 日(全天)进行维护,期间无法编辑任何页面或发布新的评论。

全站通知:

模组:物品数据

来自星露谷物语维基
跳到导航 跳到搜索

目录

本页面解释游戏如何存储和解析物品数据。这是一个面向模组开发者的高级指南。

特别注意: 此页面严格区分术语物品(item)和物体(object)。参见模组:物体

综述

物品ID

在游戏数据中,我们通过物品ID表示物品。物品ID具有如下两种形式:

  • 非限定性物品ID(unqualified item ID,对应于item.ItemId)是某个物品的唯一字符串ID,例如123(原版物品)或Example.ModId_Watermelon(自定义物品)。由于历史遗留因素,原版物品的非限定性物品ID可能有重复;例如,河豚(物体 128)和蘑菇箱(大型打造品 128)的非限定性物品ID都是128
  • 限定性物品ID(qualified item ID,对应于item.QualifiedItemId)则不会有重复,它是物品的类型ID和非限定性ID的组合,例如(O)128代表ID为128的物体

安装了 SMAPI 后,您可以使用运行 list_items 控制台命令以搜索物品ID。

注意: 早于星露谷 1.6 版本的模组可能会使用 item.ParentSheetIndex 字段来识别物品。这并不是一种有效的方法,因为即使是同一类型的物品也可能位于不同的贴图集中,因而可能拥有相同的贴图索引。

物品类型

物品是通过相应的 DataDefinition类而被定义的。每种 DataDefinition 类会处理对应类型的物品。例如,游戏的 ObjectDataDefinition 类负责解析 Data/Objects 数据素材并创建“物体”类型的物品

每种物品类型都有唯一的ID,例如 (O),它们用于构建全局唯一的限定性物品ID。在 C# 代码中,类型ID记录在 item.TypeDefinitionId 字段。对于原版物品类型,其值与 ItemRegistry.type_* 常量一致。

如下列出了自定义物品可以添加/编辑的物品类型:

物品类型 类型标识符 数据素材 概述
物体 (O) Data/Objects 最常见的物品类型。根据具体数据,它们能够被放在地上、捡起、食用、售出等。
大型打造品 (BC) Data/BigCraftables 能被放在地上、两地块高的物品(而不是像物体那样一个地块高)。
靴子 (B) Data/Boots 能够被放进靴子栏的物品。靴子能改变玩家贴图,并且可能提供加成。
家具 (F) Data/Furniture 可以被放下的装饰性物品。某些情况下玩家可以坐在其上,或在其上放置物品。
帽子 (H) Data/Hats 能够被放进玩家的帽子栏的物品。可以改变玩家贴图。
假人模特 (M) Data/Mannequins 可以被放在地上的装饰性物品,用于存放和展示衣物。
裤子 (P) Data/Pants 可以被放进玩家的裤子栏的物品。可以改变玩家贴图。
上衣 (S) Data/Shirts 可以被放进玩家的上衣栏的物品。可以改变玩家贴图。
工具 (T) Data/Tools 可以被玩家挥舞或使用、发挥特定功效(挖土、砍树、挤奶、剪毛等)的物品。
饰品 (TR) Data/Trinkets 能够被放进玩家的饰品栏以提供特定效果的物品。
墙纸和地板 (WP) and (FL) Data/AdditionalWallpaperFlooring 可以被应用于可装饰地点(例如农舍畜棚)、改变地板或墙壁样式的物品。(区别于红砖地板等可放置物品。)
武器 (W) Data/Weapons 能够被玩家挥舞或使用以杀伤怪物的物品。

当游戏尝试解析非限定性物品ID(例如 128)时,游戏会按如下顺序检索物品类型,并返回第一个可用的类型对应的物品:物体、大型打造品、家具、武器、靴子、帽子、假人模特、裤子、上衣、工具、饰品、墙纸和地板。

物品贴图

对于每个物品类型,游戏都在 Content 目录下有对应的两个文件(可以解包以编辑):

  • 数据素材用于存储此类型的物品的文本数据(包括名称、描述、价格等);
  • 贴图集用于存储物品在游戏内的图标。

每个物品都有一个 ParentSheetIndex 字段用于指示其在相应贴图集中的位置,左上角的索引为 0 ,然后按左到右、从上到下的顺序依次加一。例如,帽子 #0 指代 Characters/Farmer/hats 贴图集中的第一个贴图。

定义自定义物品

对于大多数原版物品类型,您可以仅利用 Contenet PatcherSMAPI 的 Content 接口

例如,下面给出的内容包添加了一个自定义的河豚鸡(Pufferchick)物品,包括自定义图像、自定义礼物喜好、产出它的自定义作物。注意在其他数据素材中(例如Data/CropsData/NPCGiftTastes),物品引用须使用物品ID。

{
    "Format": "2.7.0",
    "Changes": [
        // add item
        {
            "Action": "EditData",
            "Target": "Data/Objects",
            "Entries": {
                "{{ModId}}_Pufferchick": {
                    "Name": "{{ModId}}_Pufferchick", // best practice to match the ID, since it's sometimes used as an alternate ID (e.g. in Data/CraftingRecipes)
                    "Displayname": "Pufferchick",
                    "Description": "An example object.",
                    "Type": "Seeds",
                    "Category": -74,
                    "Price": 1200,

                    "Texture": "Mods/{{ModId}}/Objects",
                    "SpriteIndex": 0
                }
            }
        },

        // add gift tastes
        {
            "Action": "EditData",
            "Target": "Data/NPCGiftTastes",
            "TextOperations": [
                {
                    "Operation": "Append",
                    "Target": ["Entries", "Universal_Love"],
                    "Value": "{{ModId}}_Pufferchick",
                    "Delimiter": " " // if there are already values, add a space between them and the new one
                }
            ]
        },

        // add crop (Pufferchick is both seed and produce, like coffee beans)
        {
            "Action": "EditData",
            "Target": "Data/Crops",
            "Entries": {
                "{{ModId}}_Pufferchick": {
                    "Seasons": [ "spring", "summer", "fall" ],
                    "DaysInPhase": [ 1, 1, 1, 1, 1 ],
                    "HarvestItemId": "{{ModId}}_Pufferchick",

                    "Texture": "Mods/{{ModId}}/Crops",
                    "SpriteIndex": 0
                }
            }
        },

        // add item + crop images
        {
            "Action": "Load",
            "Target": "Mods/{{ModId}}/Crops, Mods/{{ModId}}/Objects",
            "FromFile": "assets/{{TargetWithoutPath}}.png" // assets/Crops.png, assets/Objects.png
        }
    ]
}

大多数物品数据素材的工作方式就像Data/Objects。另请参阅关于自定义果树自定义工具近战武器的详细信息。

错误物品

当由于某个物品(因为删除所在模组等原因)损坏时,它在游戏中就会变为默认的错误物品,并显示 🛇 贴图。错误物品会保留先前的物品数据,以备后期重新补回物品数据。

公共数据

品质

每个物品都有一个品质等级,该等级(依赖于物品类型)可能影响物品的售价、生命值回复等。可用的品质如下:

品质 数值 常量
普通 0 Object.lowQuality
银星 1 Object.medQuality
金星 2 Object.highQuality
铱星 4 Object.bestQuality

类别

每个物品都有一个类别(使用负整数表示)。在代码中,可以通过item.Category获取物品类别,以及可以通过item.getCategoryName()获取其翻译后的名称。可用的类别如下:

数值 常量 上下文标签 中文翻译 性质
-2 Object.GemCategory category_gem 矿物 宝石专家职业影响。
-4 Object.FishCategory category_fish 渔夫垂钓者职业影响。
-5 Object.EggCategory category_egg 动物制品 畜牧人职业影响。可用于弹弓。
-6 Object.MilkCategory category_milk 动物制品 畜牧人职业影响。
-7 Object.CookingCategory category_cooking 菜品
-8 Object.CraftingCategory category_crafting 制造品 可放置
-9 Object.BigCraftableCategory category_big_craftable 可放置
-12 Object.mineralsCategory category_minerals 矿物 宝石专家职业影响。
-14 Object.meatCategory category_meat 动物制品
-15 Object.metalResources category_metal_resources 资源
-16 Object.buildingResources category_building_resources 资源
-17 Object.sellAtPierres category_sell_at_pierres
-18 Object.sellAtPierresAndMarnies category_sell_at_pierres_and_marnies 动物制品 畜牧人职业影响。
-19 Object.fertilizerCategory category_fertilizer 肥料 可放置、可穿行
-20 Object.junkCategory category_junk 垃圾
-21 Object.baitCategory category_bait 鱼饵 可以用于钓竿。
-22 Object.tackleCategory category_tackle 鱼钩 可以用于钓竿。不可堆叠。
-23 sellAtFishShopCategory category_sell_at_fish_shop
-24 Object.furnitureCategory category_furniture 装饰
-25 Object.ingredientsCategory category_ingredients 菜品
-26 Object.artisanGoodsCategory category_artisan_goods 工匠物品 工匠职业影响。
-27 Object.syrupCategory category_syrup 工匠物品 萃取者职业影响。
-28 Object.monsterLootCategory category_monster_loot 怪物战利品
-29 Object.equipmentCategory category_equipment
-74 Object.SeedsCategory category_seeds 种子 可放置。可穿行。
-75 Object.VegetableCategory category_vegetable 蔬菜 农耕人职业影响。可用于弹弓。
-79 Object.FruitsCategory category_fruits 水果 农耕人职业影响(若非采集水果)。可用于弹弓。
-80 Object.flowersCategory category_flowers 农耕人职业影响。
-81 Object.GreensCategory category_greens 采集品
-95 Object.hatCategory category_hat
-96 Object.ringCategory category_ring
-97 Object.bootsCategory category_boots
-98 Object.weaponCategory category_weapon
-99 Object.toolCategory category_tool
-100 Object.clothingCategory category_clothing
-101 Object.trinketCategory category_trinket
-102 Object.booksCategory
-103 Object.skillBooksCategory
-999 Object.litterCategory category_litter

上下文标签

上下文标签是附加在物品上的任意数据标签,例如 category_gemitem_apple。它们提供了物品的元数据(例如颜色、品质、类别、大体上的分类比如酒或鱼 等),且可能影响游戏逻辑(例如,机器处理)。

参见模组:上下文标签以获取更多信息。

特定物品类型

如需了解某个具体数据类型(如物体或武器),请参阅上述物品类型表格。

关于C#模组

识别物品

您可以检查物品ID字段以识别物品。例如:

bool isPufferfish = item.QualifiedItemId == "(O)128";

ItemRegistry 类也提供了处理物品的方法,例如:

// 检查物品是否匹配限定性或非限定性物品ID
bool isPufferfish = ItemRegistry.HasItemId(item, "128");

// 如有需要,将非限定性ID转为限定性
string pufferfishQualifiedId = ItemRegistry.QualifyItemId("128"); // returns "(O)128"

注意,风味物品(例如果酱果酒)没有单独的ID。例如,“蓝莓果酒”和“果酒”的ID都是(O)348。您可以通过 preservedParentSheetIndex 字段获取其原材料ID;例如,蓝莓果酒的原材料ID为蓝莓的ID(虽然此字段名为“贴图集索引”,但实际上包含的是原材料的物品ID)。

创建物品实例

ItemRegistry.Create 方法是创建物品的主要途径。例如:

Item pufferfish = ItemRegistry.Create("(O)128"); // can optionally specify count and quality

若ID不能匹配任何真实存在的物品,则 ItemRegistry 默认返回一个错误物品。此逻辑可以被重写,具体来说是在调用方法时传入 allowNull: true

如有需要,您也可以使该方法返回特定类型的对象,而不是默认返回 Item 对象。如果物品类型不兼容(例如把家具转换为靴子),则会抛出一则描述性的异常。

Boots boots = ItemRegistry.Create<Boots>("(B)505"); // Rubber Boots

如果需要手动创建物品,请确保向构造函数传入的是ItemId而不是 QualifiedItemId)。例如:

Item pufferfish = new Object("128", 1);

处理物品元数据

ItemRegistry 类提供了几种方法用于处理物品元数据。下面列出了一些实用的方法:

方法 效果
ItemRegistry.Create 创建一个物品实例
ItemRegistry.Exists 获知某个限定性或非限定性物品ID是否可以匹配真实存在的物品。例如:
bool pufferfishExists = ItemRegistry.Exists("(O)128");
ItemRegistry.IsQualifiedId 获知给定的物品ID是否添加了限定性前缀(例如(O)128128)。
ItemRegistry.QualifyItemId 根据输入的限定性或非限定性物品ID,返回对应的限定性物品ID。例如:
string qualifiedId = ItemRegistry.QualifyItemId("128"); // returns (O)128
ItemRegistry.GetMetadata 获取物品的高级信息:
// 获取橡胶靴的信息
ItemMetadata metadata = ItemRegistry.GetMetadata("(B)505");

// 获取物品ID信息
$"The item has unqualified ID {metadata.LocalId}, qualified ID {metadata.QualifiedId}, and is defined by the {metadata.TypeIdentifier} item data definition.";

// 物品是否存在于数据文件中?
bool exists = metadata.Exists();

获取物品通用的、解析后的数据:

// 获取解析后的信息
ParsedItemData data = info.GetParsedData();
$"The internal name is {data.InternalName}, translated name {data.DisplayName}, description {data.Description}, etc.";

// 绘制物品贴图
Texture2D texture = data.GetTexture();
Rectangle sourceRect = data.GetSourceRect();
spriteBatch.Draw(texture, Vector2.Zero, sourceRect, Color.White);

创建物品:

Item item = metadata.CreateItem();

获取类型定义(注意,此操作高度专业化。通常情况下您应当转而使用ItemRegistry,以获取缓存和优化上的好处):

IItemDataDefinition typeDefinition = info.GetTypeDefinition();
ItemRegistry.ResolveMetadata 相当于ItemRegistry.GetMetadata,除了物品不存在时会返回空值。
ItemRegistry.GetData 获取某个物品解析后的数据,若不存在则返回null。这是ItemRegistry.ResolveMetadata(id)?.GetParsedData()的简写;参见前一方法以获得关于解析后的数据的信息。
ItemRegistry.GetDataOrErrorItem 相当于ItemRegistry.GetData,除了物品不存在时会返回错误物品的信息(例如,在物品栏中绘制)。
ItemRegistry.GetErrorItemName 获取翻译后的错误物品标签。

定义自定义物品类型

您可以实现IItemDataDefinition以自定义物品类型,并调用ItemRegistry.AddTypeDefinition以注册之。这提供了游戏所需的处理物品类型的一切逻辑:何处获取物品数据、如何绘制物品等等。

自定义物品类型是极其专业化的,且对于多人游戏的兼容性未知。大部分模组应当添加属于已有类型的物品,而非新建类型。