饥荒联机版Mod开发:从零开始,手把手教你给烹饪锅添加自定义食物(附完整代码)

osakadorisss

饥荒联机版Mod开发实战:烹饪锅自定义食物全流程指南

第一次打开饥荒联机版的Mod文件夹时,那些密密麻麻的代码和陌生的文件结构确实让人望而生畏。但别担心,今天我们就用最直白的语言,从零开始教你如何为烹饪锅添加一个会"变魔术"的趣味食物——当你吃下它时,会从天上掉下树枝!这个教程专为完全没接触过Mod开发的玩家设计,每个步骤都附带详细解释和完整代码,确保你能跟着做出来。

1. 开发前的准备工作

在开始编写代码前,我们需要先搭建好Mod的基础框架。就像盖房子需要先打地基一样,这些准备工作能让后续开发事半功倍。

1.1 创建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文件夹"即可快速定位。

1.2 必备文件详解

每个文件都有其特定用途,我们来逐一了解:

  1. modicon.texmodicon.xml

    • 这是Mod的图标,显示在游戏Mod列表中
    • 尺寸必须为128×128像素
    • 可以使用TEX编辑器或Photoshop等工具创建
  2. modinfo.lua

    • Mod的元信息文件,包含名称、作者、描述等基本信息
    • 基础模板如下:
lua复制name = "魔法食物Mod"
description = "添加会变魔术的趣味食物"
author = "你的名字"
version = "1.0.0"

api_version = 10

dst_compatible = true
client_only_mod = false
all_clients_require_mod = true
  1. modmain.lua

    • Mod的主入口文件,所有核心逻辑都在这里加载
    • 我们稍后会详细填充内容
  2. images/inventoryimages/

    • 存放物品在背包中的图标
    • 尺寸应为64×64像素
  3. exported/

    • 存放食物的动画文件
    • 推荐尺寸为140×140像素

2. 制作食物贴图与动画

没有视觉表现的食物就像没有包装的礼物,我们先来解决这个问题。

2.1 创建物品图标

images/inventoryimages/文件夹中,你需要准备两个文件:

  1. magic_food.tex - 物品图标纹理文件
  2. magic_food.xml - 图标描述文件

XML文件内容如下:

xml复制<Atlas>
    <Texture filename="magic_food.tex" />
    <Elements>
        <Element name="magic_food.tex" u1="0" u2="1" v1="0" v2="1" />
    </Elements>
</Atlas>

注意:如果你不熟悉图像编辑,可以先使用游戏内已有的食物贴图作为临时替代,只需将文件名和引用路径对应修改即可。

2.2 准备食物动画

食物动画需要更专业的工具,这里提供一个简化方案:

  1. exported/文件夹中创建magic_food.zip
  2. 这个压缩包应包含:
    • build.bin - 动画构建文件
    • anim.bin - 动画数据文件

对于初学者,可以从其他Mod中复制一个简单的食物动画文件,重命名为magic_food.zip作为起点。后期熟悉后,可以用Spriter等工具创建自定义动画。

3. 编写食物核心逻辑

现在进入最关键的代码部分,我们会分模块讲解,确保你理解每一行代码的作用。

3.1 定义食物属性(myfoods.lua)

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

3.2 创建食物实体(prefabs/myfoods.lua)

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)

4. 整合到烹饪系统

最后一步,我们需要将食物添加到游戏的烹饪系统中。

4.1 修改modmain.lua

打开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 = "吃了它会变魔术!"

4.2 测试与调试

完成以上步骤后,启动游戏并激活你的Mod。在游戏中,你应该能够:

  1. 在任何烹饪锅中制作这个魔法食物(不需要任何材料)
  2. 食用后会在玩家头顶生成一个树枝
  3. 在物品栏中看到正确的图标和描述

如果遇到问题,检查以下几个方面:

  • 所有文件路径是否正确
  • 文件名是否一致(注意大小写)
  • 游戏日志(位于Documents/Klei/DoNotStarveTogether/client_log.txt)中的错误信息

5. 进阶优化与扩展

基础功能实现后,我们可以进一步优化这个Mod。

5.1 添加烹饪条件

修改myfoods.lua中的test函数,添加实际的烹饪条件:

lua复制test = function(cooker, names, tags)
    return (tags.veggie or 0) >= 1 and (tags.fruit or 0) >= 1
end

这样设置后,制作魔法食物需要至少1个蔬菜类和1个水果类食材。

5.2 添加更多食物效果

我们可以扩展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

5.3 添加自定义音效

在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")
}

内容推荐

ESP8266Audio实战:从零构建软件模拟音频播放系统
本文详细介绍了如何使用ESP8266和ESP8266Audio库从零构建软件模拟音频播放系统。内容涵盖环境配置、硬件连接、代码实现及常见问题排查,特别适合物联网开发者和硬件爱好者学习低成本音频解决方案。通过实战案例展示如何优化音质、降低功耗,并扩展智能闹钟等应用场景。
Tektronix TBS1102B示波器精准测量电压的实战指南
本文详细介绍了Tektronix TBS1102B示波器在精准测量电压方面的实战技巧,包括探头校准、直流/交流电压测量、特殊波形处理及误差分析等关键步骤。通过具体案例和操作指南,帮助工程师避免常见测量陷阱,提升测试精度,特别适合电子测试和工程调试场景。
STM32 HAL库中uwTickFreq异常归零,导致HAL_Delay()死循环的排查与解决实录
本文详细分析了STM32 HAL库中uwTickFreq异常归零导致HAL_Delay()死循环的问题,提供了四种实战验证的解决方案。通过深入解析HAL_Delay()工作原理和关键变量追踪,帮助开发者快速定位并修复这一常见但棘手的嵌入式系统故障,提升STM32开发效率。
Win11下轻量化部署MSVC:告别臃肿VS,精准构建C++开发环境
本文详细介绍了在Win11系统下轻量化部署MSVC的方法,帮助开发者告别臃肿的Visual Studio,精准构建C++开发环境。通过精简安装MSVC工具链和Windows SDK,节省硬盘空间并提升编译效率,同时提供环境配置和常见问题排查的实用技巧。
告别像素级搜索:用Ultra Fast Lane Detection的‘格子分类’法,5分钟搞定车道线检测模型部署
本文详细解析了Ultra Fast Lane Detection模型的车道线检测新范式,通过创新的‘格子分类’方法将连续空间离散化为固定网格,显著提升检测速度与精度。文章涵盖模型架构、数据处理流程、损失函数设计及参数调优实战,为自动驾驶和ADAS领域提供高效部署方案。
04_实战指南_阿里云OSS环境变量配置避坑与自动化脚本
本文详细解析了阿里云OSS环境变量配置中的常见错误与解决方案,包括命令行和图形界面两种配置方式的实战对比,并提供了Windows和Linux/MacOS的自动化配置脚本。特别强调了企业级安全实践,如避免硬编码AccessKey、使用RAM子账号等,帮助开发者高效避坑并提升安全性。
从零到一:基于Quartus II与Verilog的FPGA四选一多路选择器实战指南
本文详细介绍了基于Quartus II与Verilog的FPGA四选一多路选择器实现方法,从基础概念到开发环境搭建,再到Verilog代码实现、功能仿真、硬件验证及进阶优化。通过实战指南帮助读者掌握FPGA开发流程,提升数字电路设计能力,特别适合初学者和电子工程师参考。
嵌入式网络编程:别再用netif的up标志判断IP地址了!lwIP 2.x的正确姿势
本文深入解析了lwIP 2.x中网络接口状态与IP地址判定的正确方法,指出开发者应避免使用netif的up标志判断IP地址有效性。通过对比1.4.x与2.x版本的差异,详细介绍了新版接口状态管理机制、IP地址检查的正确姿势及常见场景下的状态判断,帮助嵌入式开发者避免潜在逻辑错误。
告别CPU搬运工:手把手教你用Exynos 4412的PL330 DMA实现内存到串口的高速传输
本文详细介绍了如何在Exynos 4412处理器上使用PL330 DMA控制器实现内存到串口的高速数据传输。通过寄存器配置、DMA微指令编程和性能优化技巧,开发者可以显著提升嵌入式系统的数据传输效率,降低CPU负载。文章还提供了UART高速传输的完整实现流程和性能对比测试,展示了DMA技术在嵌入式开发中的实际应用价值。
六、USB PD协议层之请求与协商:数据消息如何驱动供电合同
本文深入解析USB PD协议层中请求与协商机制,揭示数据消息如何驱动供电合同。通过剖析Request Message的关键字段如Object Position和Capability Mismatch,展示PD协议动态协商的智能特性,并分享实战中的电力管理策略与安全机制,帮助开发者优化设备充电性能。
ROS系列(四):从理论到实践,详解坐标系转换与多传感器数据对齐
本文深入探讨ROS中坐标系转换与多传感器数据对齐的核心技术,涵盖WGS-84、ECEF、ENU等常见坐标系解析及实战应用。通过TF2库实现精确的空间对齐,结合硬件同步与软件插值解决时间同步问题,提升自动驾驶、机器人等系统的数据融合精度。文章还提供典型问题排查指南和可视化调试技巧,助力开发者规避常见陷阱。
PAT甲级L2-013『红色警报』:用并查集和DFS两种思路搞定连通性判断(附C++/Python代码)
本文深入解析PAT甲级L2-013『红色警报』问题,通过并查集和DFS两种算法实现动态连通性判断。详细对比了两种解法的时间复杂度与适用场景,提供C++/Python代码示例,帮助读者掌握图论中的关键算法技巧,提升算法竞赛解题能力。
MATLAB通信仿真避坑指南:手把手教你用convenc和vitdec函数搞定卷积码(附完整代码)
本文详细解析了MATLAB中卷积码编解码函数`convenc`和`vitdec`的实战应用,涵盖网格结构初始化、参数配置、译码模式对比及高级调试技巧。通过完整代码示例和典型问题解决方案,帮助工程师避开常见陷阱,提升通信系统仿真效率。特别针对信道编码中的卷积编译码技术提供了实用指南。
从“一把梭”到“精确定位”:fscan高级参数实战指南,教你如何定制化扫描避免“误伤”和流量异常
本文深入探讨了fscan内网扫描工具的高级参数使用技巧,帮助用户从全量扫描转向精确定位。通过控制扫描噪音、选择特定模块和端口、调整速率以及使用代理等策略,有效避免触发安全设备的告警和流量异常,提升渗透测试的隐蔽性和效率。
别再只用IForest了!用Python的sklearn实战LOF异常检测,识别信用卡欺诈和工业缺陷
本文详细介绍了如何使用Python的sklearn库实战LOF(局部离群因子)异常检测算法,特别适用于信用卡欺诈和工业缺陷检测等场景。通过对比IForest算法,LOF在处理密度不均、局部异常集群和边界模糊的异常时表现更优。文章提供了完整的代码示例和参数调优建议,帮助开发者快速掌握这一强大的机器学习工具。
IMU标定实战:从Allen方差到随机误差分析的完整方案
本文详细介绍了IMU标定的完整流程,从确定性误差补偿到随机误差分析,特别强调了Allen方差在评估IMU随机误差中的关键作用。通过imu_tk工具的实际操作指南和Allen方差分析,帮助开发者构建高精度IMU数据处理方案,提升数据可靠性。
STM32H750实战:CubeMX配置SPI驱动中景园ST7789屏的三大避坑点(附GitHub工程)
本文详细解析了STM32H750通过CubeMX配置SPI驱动中景园ST7789屏幕时的三大关键避坑点,包括SPI时钟频率优化、屏幕初始化代码移植技巧及GPIO抽象层设计。特别针对30MHz稳定时钟配置、硬件SPI适配和分层驱动架构进行实战指导,并附GitHub工程源码,助力开发者高效完成嵌入式显示开发。
C#文件操作避坑大全:复制、移动文件时如何优雅处理路径、权限和异常?
本文详细介绍了C#文件操作中的常见问题及解决方案,包括路径处理、异常处理、权限管理和特殊场景优化。通过实战案例和代码示例,帮助开发者优雅处理文件复制、移动中的路径、权限和异常问题,提升代码健壮性和跨平台兼容性。
LVGL Switch控件从入门到精通:手把手教你实现炫酷开关动画与事件响应(附完整代码)
本文深入解析LVGL Switch控件的开发技巧,从三层结构解剖到动画效果高级配置,再到事件处理与性能优化。通过完整代码示例,帮助开发者实现炫酷开关动画与智能交互,提升嵌入式GUI的用户体验。特别适合嵌入式系统开发者学习LVGL控件的高级应用。
STM32CubeMX生成Makefile,再用Segger Embedded Studio导入的保姆级避坑指南
本文详细解析了如何使用STM32CubeMX生成Makefile,并通过Segger Embedded Studio(SES)导入工程的完整流程。涵盖环境准备、工程配置、常见问题排查及性能优化,特别适合追求跨平台开发的嵌入式工程师。文章提供了关键步骤和实用技巧,帮助开发者高效搭建开发环境并避免常见陷阱。
已经到底了哦
精选内容
热门内容
最新内容
从10折交叉验证到留一法:如何为你的模型选择最佳验证策略
本文深入探讨了机器学习中10折交叉验证和留一法两种核心验证策略的优缺点及适用场景。10折交叉验证(10-fold Cross Validation)作为平衡效率与准确性的黄金标准,适合中等规模数据集;而留一法(Leave-One-Out)则是小样本场景下的终极武器。文章通过代码实例和实战经验,指导开发者根据数据规模、模型复杂度和业务需求选择最佳验证方法。
蓝桥杯单片机实战:DS18B20温度传感器驱动与数据解析全流程
本文详细介绍了在蓝桥杯单片机竞赛中使用DS18B20温度传感器的全流程,包括单总线(onewire)通信协议、温度数据读取与解析技巧。通过实战经验和优化建议,帮助参赛者快速掌握传感器驱动开发,提升比赛中的开发效率和稳定性。
IntelliJ IDEA里运行正常,一打Jar包就报NoClassDefFoundError?可能是Logback在捣鬼
本文深入分析了IntelliJ IDEA中运行正常但打包成JAR后出现NoClassDefFoundError的问题,特别是与Logback相关的ThrowableProxy类缺失问题。文章详细解释了类加载机制差异,提供了Maven配置检查、依赖冲突解决、打包配置调整等实用解决方案,并分享了验证调试技巧和预防措施,帮助开发者彻底解决这一常见但棘手的日志系统问题。
从原理到选型:深入解读力矩传感器的核心性能与工业应用
本文深入解析力矩传感器的工作原理、核心性能指标及工业应用场景。从应变片原理到惠斯通电桥设计,详细介绍了力矩传感器如何实现精准力值测量,并重点分析了串扰、过载能力等关键性能指标。通过汽车测试、机器人等实际案例,提供选型建议和安装调试技巧,帮助工程师在工业自动化中优化力矩传感器的使用。
Keil MDK AC6编译后printf不打印?手把手教你修复串口重定向(附ST官方方案)
本文详细解析了Keil MDK从AC5迁移到AC6后printf失效的问题,提供了三种解决方案,包括ST官方推荐的跨工具链兼容方案。通过对比AC5与AC6的核心差异,帮助开发者快速修复串口重定向问题,确保调试信息正常输出。
别再只用Notion了!用Docker在NAS上5分钟自建一个实时协作的Markdown编辑器HedgeDoc
本文详细介绍了如何在NAS上使用Docker快速部署HedgeDoc,一个专为Markdown爱好者设计的实时协作编辑器。通过5分钟的简单配置,即可实现私有化部署,享受数据自主权和极简协作体验,特别适合技术团队和远程工作者。
保姆级教程:手把手教你用JVS低代码平台搭建私有化钉钉审批流(含分支与会签配置)
本文提供了一份详细的JVS低代码平台教程,指导用户如何搭建私有化钉钉审批流,包括分支与会签配置。通过卡片式配置和流程审批设计,帮助企业实现高效、安全的审批流程自动化,特别适合有数据安全需求的企业。
从SPI到I2C:在Xilinx Vivado里用Verilog搭建一个可配置的串行通信IP核
本文详细介绍了如何在Xilinx Vivado中使用Verilog设计一个可配置的串行通信IP核,支持SPI四种模式切换并预留I2C扩展接口。通过参数化设计和状态机实现,该IP核可以动态配置CPOL/CPHA、数据位宽和时钟分频,显著提升FPGA开发效率。文章还涵盖了Vivado IP封装、测试验证策略以及性能优化技巧。
Unity结合Vuforia:从零构建实体物体AR交互应用
本文详细介绍了如何使用Unity结合Vuforia从零构建实体物体AR交互应用。通过咖啡杯AR展示项目的实战案例,讲解了环境配置、模型目标创建、交互逻辑实现等关键步骤,并提供了性能优化与调试技巧,帮助开发者快速掌握AR开发核心技术。
别再死记硬背了!用Python+Matplotlib手把手仿真四种脉冲雷达信号(附完整代码)
本文通过Python+Matplotlib实战演示四种脉冲雷达信号的仿真实现,包括固定频率脉冲、线性调频(LFM)、捷变频和相位编码信号。详细解析雷达核心参数与波形特征,提供完整代码示例,帮助读者直观理解相参雷达信号处理技术,提升雷达系统仿真与信号分析能力。