玩过《饥荒》的朋友都知道,游戏中最让人抓狂的体验之一就是制作复杂物品时的多级合成流程。想象一下这样的场景:你正被一群猎狗追赶,急需制作一个木甲保命,却发现背包里只有木头和干草。这时候你必须先停下来,打开制作菜单,找到绳子配方,制作两根绳子,然后再回去找木甲配方。这一通操作下来,猎狗早就把你咬得七荤八素了。
这种"原材料→中间材料→成品"的多级合成机制,在游戏中有大量实例:
原版游戏的设计理念可能是为了增加生存难度,但实际体验就是纯粹的机械重复劳动。更糟糕的是,游戏制作界面没有智能推荐功能,每次都要在几十个配方中手动翻找需要的中间材料。我在实际开发mod时统计过,一个熟练玩家制作高级物品时,平均要花费30%的时间在查找配方和制作中间材料上。
我们的解决方案是在原有制作界面增加一个智能按钮,当检测到以下条件时自动显示:
技术实现上主要修改两个游戏组件:
关键点在于重写RecipePopup的Refresh方法,在每次打开制作菜单时动态检查材料情况。这里用到了典型的面向切面编程(AOP)思想,通过AddClassPostConstruct在不修改原代码的情况下扩展功能。
让我们拆解核心代码的逻辑流程:
lua复制-- 引入ImageButton控件
local ImageButton = GLOBAL.require "widgets/imagebutton"
-- 修改RecipePopup控件行为
AddClassPostConstruct("widgets/recipepopup", function(self)
-- 保存原始Refresh方法
local old = self.Refresh
-- 重写Refresh方法
self.Refresh = function(...)
-- 先执行原始刷新逻辑
old(...)
-- 如果弹窗未显示则直接返回
if not self.shown then return end
-- 获取当前配方和玩家角色
local recipe = self.recipe
local owner = self.owner
-- 隐藏已有doAction按钮
if self.doAction then self.doAction:Hide() end
-- 遍历配方所有材料
for k,v in pairs(recipe.ingredients) do
-- 检查材料本身是否是合成物品
local slotrecipe = GLOBAL.Recipes[v.type]
if slotrecipe then
-- 检查玩家是否知道配方、能否制作、材料是否足够
local knows = owner.components.builder:KnowsRecipe(v.type)
local can_build = owner.components.builder:CanBuild(v.type)
local has, num_found = owner.components.inventory:Has(v.type,
GLOBAL.RoundUp(v.amount * owner.components.builder.ingredientmod), true)
-- 满足条件时创建"材料"按钮
if knows and can_build and not has and not self.doAction then
self.doAction = self.contents:AddChild(ImageButton(
"images/ui.xml",
"button_small.tex",
"button_small_over.tex",
"button_small_disabled.tex"))
self.doAction:SetPosition(220, 140)
self.doAction:SetText("材料")
self.doAction:MoveToFront()
self.doAction:SetOnClick(function()
GLOBAL.DoRecipeClick(self.owner, self.doAction.slotrecipe)
end)
end
-- 更新按钮状态
if knows and can_build and not has then
self.doAction.slotrecipe = slotrecipe
self.doAction:Show()
end
-- 提示需要制作原型
if not knows and can_build then
owner.components.talker:Say(GLOBAL.STRINGS.NAMES[string.upper(slotrecipe.name)].."(需要制作一个原型)")
end
end
end
end
end)
这段代码的精妙之处在于:
让我们看两个最常见的应用实例:
场景一:制作木牌
场景二:紧急制作木甲
经过多次实测,我发现几个提升效率的小技巧:
一个实用的自定义修改是为按钮添加材料数量提示:
lua复制-- 在SetText后添加
self.doAction:SetHoverText("需要"..v.amount.."个"..GLOBAL.STRINGS.NAMES[string.upper(v.type)])
在实际使用中,可能会遇到按钮不显示的情况,主要检查以下几点:
如果遇到与其他修改制作系统的mod冲突,可以采用以下解决方案:
lua复制-- 安全模式检查
if rawget(GLOBAL, "RecipePopup") and not GLOBAL.RecipePopup.__modified then
-- 原有修改代码
GLOBAL.RecipePopup.__modified = true
end
对于特别复杂的mod组合,建议使用以下优先级控制机制:
在大型基地建设时,可能会遇到UI卡顿问题,可以通过以下优化缓解:
一个简单的延迟实现方案:
lua复制self.Refresh = function(...)
old(...)
self.inst:DoTaskInTime(0.1, function()
-- 检查代码
end)
end
经过这些优化后,即使在200+mod的大型整合包中,这个功能也能流畅运行。我在自己的服务器上实测,制作复杂物品的效率提升了至少3倍,特别是在基地建设阶段效果尤为明显。