饥荒相关-肉类工厂mod

我爱海鲸 2026-10-17 22:58:57 暂无标签

简介mod、肉类

| 优先级 | 产出 | 投入条件(凑满 4 格) | 示例 |
| --- | --- | --- | --- |
| 1 | 猪皮 | 纯正常肉,肉价值 ≥ 2,且无怪物肉/蔬菜/水果/鱼/蛋 | 2 大肉;1 大肉 + 2 小肉;4 小肉 |
| 2 | 怪物肉 | 混入怪物肉(怪物价值 ≥ 1 且 肉价值 ≥ 1) | 1 怪物肉 + 任意 3 个食物 |
| 3 | 大肉 | 蔬菜价值 ≥ 4 或 水果价值 ≥ 4 | 4 胡萝卜;4 玉米 |
| 4 | 鱼肉 | 鱼价值 ≥ 1.5 | 2 鱼 + 2 任意 |
| 5 | 鸡腿 | 蛋价值 ≥ 2 | 2 鸟蛋 + 2 任意 |
| 6 | 小肉 | 兜底(以上都不满足) | 任意 4 个食物 |

目录:I:\WeGameApps\rail_apps\饥荒:联机版(2000004)\mods

meat_factory:

scripts\prefabs\meatfactory.lua:

-- 肉类工厂结构:复用原版「烹饪锅」的 stewer 组件与动画,
-- 放入食物后经过「烹饪」转化出肉类(产出由 cooking 配方决定,见 modmain.lua)。

require "prefabutil"

local assets =
{
    Asset("ANIM", "anim/cook_pot.zip"),
    Asset("ANIM", "anim/ui_cookpot_1x4.zip"),
}

local prefabs =
{
    "collapse_small",
}

local function onhammered(inst, worker)
    if inst.components.burnable ~= nil and inst.components.burnable:IsBurning() then
        inst.components.burnable:Extinguish()
    end
    if not inst:HasTag("burnt") and inst.components.stewer.product ~= nil and inst.components.stewer:IsDone() then
        inst.components.stewer:Harvest()
    end
    if inst.components.container ~= nil then
        inst.components.container:DropEverything()
    end
    inst.components.lootdropper:DropLoot()
    local fx = SpawnPrefab("collapse_small")
    fx.Transform:SetPosition(inst.Transform:GetWorldPosition())
    fx:SetMaterial("metal")
    inst:Remove()
end

local function onhit(inst, worker)
    if not inst:HasTag("burnt") then
        if inst.components.stewer:IsCooking() then
            inst.AnimState:PlayAnimation("hit_cooking")
            inst.AnimState:PushAnimation("cooking_loop", true)
            inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_close")
        elseif inst.components.stewer:IsDone() then
            inst.AnimState:PlayAnimation("hit_full")
            inst.AnimState:PushAnimation("idle_full", false)
        else
            if inst.components.container ~= nil and inst.components.container:IsOpen() then
                inst.components.container:Close()
            else
                inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_close")
            end
            inst.AnimState:PlayAnimation("hit_empty")
            inst.AnimState:PushAnimation("idle_empty", false)
        end
    end
end

-- 动画 / 音效回调

local function startcookfn(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("cooking_loop", true)
        inst.SoundEmitter:KillSound("snd")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_rattle", "snd")
        inst.Light:Enable(true)
    end
end

local function onopen(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("cooking_pre_loop")
        inst.SoundEmitter:KillSound("snd")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_open")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot", "snd")
    end
end

local function onclose(inst)
    if not inst:HasTag("burnt") then
        if not inst.components.stewer:IsCooking() then
            inst.AnimState:PlayAnimation("idle_empty")
            inst.SoundEmitter:KillSound("snd")
        end
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_close")
    end
end

local function donecookfn(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("cooking_pst")
        inst.AnimState:PushAnimation("idle_full", false)
        inst.SoundEmitter:KillSound("snd")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_finish")
        inst.Light:Enable(false)
    end
end

local function continuedonefn(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("idle_full")
    end
end

local function continuecookfn(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("cooking_loop", true)
        inst.Light:Enable(true)
        inst.SoundEmitter:KillSound("snd")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_rattle", "snd")
    end
end

local function harvestfn(inst)
    if not inst:HasTag("burnt") then
        inst.AnimState:PlayAnimation("idle_empty")
        inst.SoundEmitter:PlaySound("dontstarve/common/cookingpot_close")
    end
end

local function getstatus(inst)
    return (inst:HasTag("burnt") and "BURNT")
        or (inst.components.stewer:IsDone() and "DONE")
        or (not inst.components.stewer:IsCooking() and "EMPTY")
        or (inst.components.stewer:GetTimeToCook() > 15 and "COOKING_LONG")
        or "COOKING_SHORT"
end

local function onbuilt(inst)
    inst.AnimState:PlayAnimation("place")
    inst.AnimState:PushAnimation("idle_empty", false)
    inst.SoundEmitter:PlaySound("dontstarve/common/cook_pot_craft")
end

local function onsave(inst, data)
    if inst:HasTag("burnt") or (inst.components.burnable ~= nil and inst.components.burnable:IsBurning()) then
        data.burnt = true
    end
end

local function onload(inst, data)
    if data ~= nil and data.burnt then
        inst.components.burnable.onburnt(inst)
        inst.Light:Enable(false)
    end
end

local function onloadpostpass(inst, newents, data)
    if data and data.additems and inst.components.container then
        for i, itemname in ipairs(data.additems) do
            local ent = SpawnPrefab(itemname)
            inst.components.container:GiveItem(ent)
        end
    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddMiniMapEntity()
    inst.entity:AddLight()
    inst.entity:AddNetwork()

    inst:SetDeploySmartRadius(1)
    MakeObstaclePhysics(inst, .5)

    inst.Light:Enable(false)
    inst.Light:SetRadius(.6)
    inst.Light:SetFalloff(1)
    inst.Light:SetIntensity(.5)
    inst.Light:SetColour(235/255, 62/255, 12/255)

    inst:AddTag("structure")
    -- stewer 标签:让 componentactions / actions 通用地识别为可烹饪结构
    inst:AddTag("stewer")

    inst.AnimState:SetBank("cook_pot")
    inst.AnimState:SetBuild("cook_pot")
    inst.AnimState:PlayAnimation("idle_empty")
    inst.MiniMapEntity:SetIcon("cookpot.png")

    MakeSnowCoveredPristine(inst)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("stewer")
    inst.components.stewer.onstartcooking = startcookfn
    inst.components.stewer.oncontinuecooking = continuecookfn
    inst.components.stewer.oncontinuedone = continuedonefn
    inst.components.stewer.ondonecooking = donecookfn
    inst.components.stewer.onharvest = harvestfn

    inst:AddComponent("container")
    inst.components.container:WidgetSetup("meatfactory")
    inst.components.container.onopenfn = onopen
    inst.components.container.onclosefn = onclose
    inst.components.container.skipclosesnd = true
    inst.components.container.skipopensnd = true

    inst:AddComponent("inspectable")
    inst.components.inspectable.getstatus = getstatus

    inst:AddComponent("lootdropper")
    inst:AddComponent("workable")
    inst.components.workable:SetWorkAction(ACTIONS.HAMMER)
    inst.components.workable:SetWorkLeft(4)
    inst.components.workable:SetOnFinishCallback(onhammered)
    inst.components.workable:SetOnWorkCallback(onhit)

    inst:AddComponent("hauntable")
    inst.components.hauntable:SetHauntValue(TUNING.HAUNT_TINY)

    MakeSnowCovered(inst)
    SetLunarHailBuildupAmountSmall(inst)
    inst:ListenForEvent("onbuilt", onbuilt)

    MakeMediumBurnable(inst, nil, nil, true)
    MakeSmallPropagator(inst)

    inst.OnSave = onsave
    inst.OnLoad = onload
    inst.OnLoadPostPass = onloadpostpass

    return inst
end

return Prefab("meatfactory", fn, assets, prefabs),
    MakePlacer("meatfactory_placer", "cook_pot", "cook_pot", "idle_empty")

modinfo.lua:

name = "Meat Factory(肉类工厂)"

description = "新增一个「肉类工厂」结构:放入食物,按不同配方转化出不同肉类(大肉、小肉、鱼肉、鸡腿)。"

author = "local"

version = "1.0.0"

forumthread = ""

api_version = 10

dst_compatible = true
all_clients_require_mod = false
client_only_mod = false

priority = 0

modmain.lua:

-- 肉类工厂(Meat Factory)
-- 结构本体见 scripts/prefabs/meatfactory.lua,这里负责:
--   1. 容器 UI(4 格,只能放入食物)
--   2. 产出配方(不同食物组合 → 不同肉类)
--   3. 建筑合成配方
--   4. 名称 / 描述 / 检查文案

PrefabFiles =
{
    "meatfactory",
}

-- 游戏全局对象不会自动暴露给 mod 沙箱,需通过 GLOBAL 引用并缓存为局部变量。
local GLOBAL = GLOBAL
local STRINGS = GLOBAL.STRINGS
local ACTIONS = GLOBAL.ACTIONS
local TECH = GLOBAL.TECH
local FOODTYPE = GLOBAL.FOODTYPE
local Vector3 = GLOBAL.Vector3
local BufferedAction = GLOBAL.BufferedAction
local SendRPCToServer = GLOBAL.SendRPCToServer
local RPC = GLOBAL.RPC

--------------------------------------------------------------------------
-- 容器 UI
--------------------------------------------------------------------------

local containers = require("containers")
local params = containers.params

local function IsFoodItem(item)
    for _, v in pairs(FOODTYPE) do
        if item:HasTag("edible_" .. v) then
            return true
        end
    end
    return false
end

params.meatfactory =
{
    widget =
    {
        slotpos =
        {
            Vector3(0, 64 + 32 + 8 + 4, 0),
            Vector3(0, 32 + 4, 0),
            Vector3(0, -(32 + 4), 0),
            Vector3(0, -(64 + 32 + 8 + 4), 0),
        },
        animbank = "ui_cookpot_1x4",
        animbuild = "ui_cookpot_1x4",
        pos = Vector3(200, 0, 0),
        side_align_tip = 100,
        buttoninfo =
        {
            text = STRINGS.ACTIONS.COOK,
            position = Vector3(0, -165, 0),
        },
    },
    acceptsstacks = false,
    type = "cooker",
}

function params.meatfactory.itemtestfn(container, item, slot)
    return not container.inst:HasTag("burnt") and IsFoodItem(item)
end

function params.meatfactory.widget.buttoninfo.fn(inst, doer)
    if inst.components.container ~= nil then
        BufferedAction(doer, inst, ACTIONS.COOK):Do()
    elseif inst.replica.container ~= nil and not inst.replica.container:IsBusy() then
        SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.COOK.code, inst, ACTIONS.COOK.mod_name)
    end
end

function params.meatfactory.widget.buttoninfo.validfn(inst)
    return inst.replica.container ~= nil and inst.replica.container:IsFull()
end

--------------------------------------------------------------------------
-- 产出配方
--
-- 放入 4 格食物并「烹饪」后,按下方优先级从高到低判定,命中第一条即产出
--(数值为食物类型价值累计,与烹饪锅一致):
--   纯正常肉(肉≥2,无怪物肉/蔬菜/水果/鱼/蛋)→ 猪皮(pigskin)
--   混入怪物肉(怪物≥1 且 肉≥1)              → 怪肉(monstermeat)
--   蔬菜或水果价值 ≥ 4                         → 大肉(meat)
--   鱼类价值 ≥ 1.5                             → 鱼肉(fishmeat)
--   蛋类价值 ≥ 2                               → 鸡腿(drumstick)
--   其他任意食物                               → 小肉(smallmeat)(兜底)
--
-- 肉类(大肉/小肉/鱼肉/怪物肉等)本身就是可投入的原料,
-- 它们通过「肉」「怪物」价值参与上面「猪皮」「怪肉」两个配方的判定。
--------------------------------------------------------------------------

local function MakeRecipe(name, priority, cooktime, stacksize, test)
    return {
        name = name,
        test = test,
        priority = priority,
        weight = 1,
        cooktime = cooktime,
        stacksize = stacksize,
        no_cookbook = true,
    }
end

local RECIPES =
{
    -- 猪皮:纯正常肉 → 皮(2 大肉,或 1 大肉 + 2 小肉,或 4 小肉 等)
    MakeRecipe("pigskin", 12, 2, 1, function(cooker, names, tags)
        return (tags.meat or 0) >= 2
            and (tags.monster or 0) == 0
            and (tags.veggie or 0) == 0
            and (tags.fruit or 0) == 0
            and (tags.fish or 0) == 0
            and (tags.egg or 0) == 0
    end),

    -- 怪肉:怪物肉混入后污染整锅(1 怪物肉 + 任意 3 个食物)
    MakeRecipe("monstermeat", 11, 2, 1, function(cooker, names, tags)
        return (tags.monster or 0) >= 1 and (tags.meat or 0) >= 1
    end),

    MakeRecipe("meat", 10, 3, 1, function(cooker, names, tags)
        return (tags.veggie or 0) >= 4 or (tags.fruit or 0) >= 4
    end),

    MakeRecipe("fishmeat", 9, 2, 1, function(cooker, names, tags)
        return (tags.fish or 0) >= 1.5
    end),

    MakeRecipe("drumstick", 8, 1, 1, function(cooker, names, tags)
        return (tags.egg or 0) >= 2
    end),

    MakeRecipe("smallmeat", 1, 1, 1, function(cooker, names, tags)
        return true
    end),
}

for _, recipe in ipairs(RECIPES) do
    AddCookerRecipe("meatfactory", recipe, true)
end

--------------------------------------------------------------------------
-- 建筑合成配方
--------------------------------------------------------------------------

AddRecipe2("meatfactory",
    { Ingredient("cutstone", 2), Ingredient("charcoal", 2), Ingredient("twigs", 4) },
    TECH.SCIENCE_ONE,
    {
        atlas = "images/inventoryimages.xml",
        image = "cookpot.tex",
        placer = "meatfactory_placer",
        min_spacing = 2,
    })

--------------------------------------------------------------------------
-- 字符串(名称 / 描述 / 检查文案)
--------------------------------------------------------------------------

STRINGS.NAMES.MEATFACTORY = "肉类工厂"
STRINGS.RECIPE_DESC.MEATFACTORY = "把食物转化出肉。"

STRINGS.CHARACTERS.GENERIC.DESCRIBE.MEATFACTORY =
{
    EMPTY = "空空如也,等它变出肉来。",
    COOKING_LONG = "正在制造肉类……",
    COOKING_SHORT = "肉快好了。",
    DONE = "肉做好了!",
    BURNT = "工厂被烧坏了。",
}

你好:我的2025

上一篇:单片机相关