第一次打开饥荒联机版的Mod文件夹时,那些密密麻麻的代码和陌生的文件结构确实让人望而生畏。但别担心,今天我们就用最直白的语言,从零开始教你如何为烹饪锅添加一个会"变魔术"的趣味食物——当你吃下它时,会从天上掉下树枝!这个教程专为完全没接触过Mod开发的玩家设计,每个步骤都附带详细解释和完整代码,确保你能跟着做出来。
在开始编写代码前,我们需要先搭建好Mod的基础框架。就像盖房子需要先打地基一样,这些准备工作能让后续开发事半功倍。
在你的饥荒联机版Mods文件夹中(通常位于Documents/Klei/DoNotStarveTogether),新建一个文件夹作为你的Mod,命名为MyMagicFoodMod。然后按照以下结构创建子文件夹和文件:
code复制MyMagicFoodMod/
├── modinfo.lua
├── modmain.lua
├── scripts/
│ ├── myfoods.lua
│ └── prefabs/
│ └── myfoods.lua
├── images/
│ └── inventoryimages/
├── exported/
└── modicon.tex
提示:如果你不确定如何找到Mods文件夹,在游戏主界面点击"Mods"按钮,然后选择"打开Mod文件夹"即可快速定位。
每个文件都有其特定用途,我们来逐一了解:
modicon.tex和modicon.xml
modinfo.lua
lua复制name = "魔法食物Mod"
description = "添加会变魔术的趣味食物"
author = "你的名字"
version = "1.0.0"
api_version = 10
dst_compatible = true
client_only_mod = false
all_clients_require_mod = true
modmain.lua
images/inventoryimages/
exported/
没有视觉表现的食物就像没有包装的礼物,我们先来解决这个问题。
在images/inventoryimages/文件夹中,你需要准备两个文件:
XML文件内容如下:
xml复制<Atlas>
<Texture filename="magic_food.tex" />
<Elements>
<Element name="magic_food.tex" u1="0" u2="1" v1="0" v2="1" />
</Elements>
</Atlas>
注意:如果你不熟悉图像编辑,可以先使用游戏内已有的食物贴图作为临时替代,只需将文件名和引用路径对应修改即可。
食物动画需要更专业的工具,这里提供一个简化方案:
exported/文件夹中创建magic_food.zipbuild.bin - 动画构建文件anim.bin - 动画数据文件对于初学者,可以从其他Mod中复制一个简单的食物动画文件,重命名为magic_food.zip作为起点。后期熟悉后,可以用Spriter等工具创建自定义动画。
现在进入最关键的代码部分,我们会分模块讲解,确保你理解每一行代码的作用。
在scripts/myfoods.lua中,我们定义食物的各种属性:
lua复制local foods = {
magic_food = {
-- 食用效果:生成树枝
oneatenfn = function(inst, eater)
if not eater then return end
local x, y, z = eater.Transform:GetWorldPosition()
SpawnPrefab("twigs").Transform:SetPosition(x, y + 1, z)
end,
-- 烹饪条件检测(这里设置为无条件)
test = function(cooker, names, tags)
return true
end,
-- 基础属性
foodtype = FOODTYPE.VEGGIE, -- 食物类型
health = 10, -- 恢复生命值
hunger = 37.5, -- 恢复饥饿值
sanity = 15, -- 恢复精神值
perishtime = TUNING.PERISH_MED, -- 腐烂时间(中等)
cooktime = 0.5, -- 烹饪时间(0.5天)
priority = 10 -- 优先级(数值越大越优先)
}
}
-- 自动填充通用属性
for k,v in pairs(foods) do
v.name = k
v.weight = v.weight or 1
v.priority = v.priority or 0
v.cookbook_atlas = "images/inventoryimages/"..v.name..".xml"
end
return foods
在scripts/prefabs/myfoods.lua中,我们创建食物在游戏中的实际表现:
lua复制local foods = require("myfoods")
local prefabs = {}
for k, v in pairs(foods) do
local assets = {
Asset("ANIM", "anim/"..v.name..".zip"),
Asset("ATLAS", "images/inventoryimages/"..v.name..".xml")
}
local fn = function()
local inst = CreateEntity()
inst.entity:AddTransform()
inst.entity:AddAnimState()
inst.entity:AddNetwork()
-- 设置动画
inst.AnimState:SetBuild(v.name)
inst.AnimState:SetBank(v.name)
inst.AnimState:PlayAnimation("idle")
MakeInventoryPhysics(inst)
MakeInventoryFloatable(inst)
inst:AddTag("preparedfood")
inst.entity:SetPristine()
if not TheWorld.ismastersim then return inst end
-- 可食用组件
inst:AddComponent("edible")
inst.components.edible.healthvalue = v.health
inst.components.edible.hungervalue = v.hunger
inst.components.edible.sanityvalue = v.sanity
inst.components.edible.foodtype = v.foodtype
if v.oneatenfn then
inst.components.edible:SetOnEatenFn(v.oneatenfn)
end
-- 其他功能组件
inst:AddComponent("inventoryitem")
inst.components.inventoryitem.atlasname = "images/inventoryimages/"..v.name..".xml"
inst:AddComponent("stackable")
inst.components.stackable.maxsize = TUNING.STACK_SIZE_SMALLITEM
inst:AddComponent("perishable")
inst.components.perishable:SetPerishTime(v.perishtime)
inst.components.perishable:StartPerishing()
inst.components.perishable.onperishreplacement = "spoiled_food"
inst:AddComponent("inspectable")
inst:AddComponent("bait")
inst:AddComponent("tradable")
MakeHauntableLaunchAndPerish(inst)
return inst
end
table.insert(prefabs, Prefab(v.name, fn, assets))
end
return unpack(prefabs)
最后一步,我们需要将食物添加到游戏的烹饪系统中。
打开modmain.lua文件,添加以下内容:
lua复制-- 预加载文件
PrefabFiles = {
"myfoods"
}
-- 简化全局变量访问
GLOBAL.setmetatable(env, {
__index = function(t, k)
return GLOBAL.rawget(GLOBAL, k)
end
})
-- 加载食物定义
local foods = require("myfoods")
-- 添加到烹饪锅
for k, v in pairs(foods) do
AddCookerRecipe("cookpot", v) -- 普通烹饪锅
AddCookerRecipe("portablecookpot", v) -- 便携烹饪锅
end
-- 本地化文本(显示名称和描述)
STRINGS.NAMES.MAGIC_FOOD = "魔术食物"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.MAGIC_FOOD = "吃了它会变魔术!"
完成以上步骤后,启动游戏并激活你的Mod。在游戏中,你应该能够:
如果遇到问题,检查以下几个方面:
Documents/Klei/DoNotStarveTogether/client_log.txt)中的错误信息基础功能实现后,我们可以进一步优化这个Mod。
修改myfoods.lua中的test函数,添加实际的烹饪条件:
lua复制test = function(cooker, names, tags)
return (tags.veggie or 0) >= 1 and (tags.fruit or 0) >= 1
end
这样设置后,制作魔法食物需要至少1个蔬菜类和1个水果类食材。
我们可以扩展oneatenfn函数,实现更丰富的效果:
lua复制oneatenfn = function(inst, eater)
if not eater then return end
local x, y, z = eater.Transform:GetWorldPosition()
-- 30%几率生成花朵,70%几率生成树枝
if math.random() < 0.3 then
SpawnPrefab("flower").Transform:SetPosition(x, y + 1, z)
else
SpawnPrefab("twigs").Transform:SetPosition(x, y + 1, z)
end
-- 给玩家添加短暂的光环效果
eater:AddDebuff("buff_superjump", "superjumpbuff")
end
在prefab定义中添加音效组件:
lua复制inst:AddComponent("soundeffect")
inst.components.soundeffect:SetOnEatenFn(function()
inst.SoundEmitter:PlaySound("dontstarve/creatures/chester/raise")
end)
记得在assets中添加音效文件的引用:
lua复制local assets = {
Asset("ANIM", "anim/"..v.name..".zip"),
Asset("ATLAS", "images/inventoryimages/"..v.name..".xml"),
Asset("SOUND", "sound/dontstarve.fsb")
}