饥荒通用升级组件
1. 组件介绍
- 组件只负责处理等级数值的改变和调用传入的函数,等级改变时执行的函数和最高级时执行的函数应该在每个预制体里定义。
- 组件含有一个标签"
前缀_upgradable",当处于可升级的状态时就自动添加该标签,可用于在AddComponentAction中判断,这个前缀是文件名的前缀,因此不同mod的升级组件相互独立。 - 组件含有配套附件,有一个网络变量current,可用于在客户端读取对象的等级。
- 组件只负责保存等级和调用两个函数,并且在加载时会根据保存的等级自动调用函数。
下面给出组件源码,统一采用前缀upt_
- 组件代码
-- scripts/components/upt_upgrade.lua
local componentPre = debug.getinfo(1, 'S').source:match("([^/]+)_upgrade%.lua$") --当前文件前缀
local componentName = componentPre .. "_upgrade"
local upgradableTag = componentPre .. "_upgradable" --可升级标签,在这里值为upt_upgradable
local function OnChanged(self)
local has = self.inst:HasTag(upgradableTag)
if self.current and self.maxLevel and self.current < self.maxLevel then
if not has then
self.inst:AddTag(upgradableTag)
end
else
if has then
self.inst:RemoveTag(upgradableTag)
end
end
end
local function oncurrent(self, current)
self.inst.replica[componentName]:SetLevel(current)
OnChanged(self)
end
--- 简单通用升级组件,只保存当前等级,其他东西都需要每次设置
local Upgrade = Class(function(self, inst)
self.inst = inst
self.initLevel = 0 --初始等级
self.current = self.initLevel --当前等级
self.maxLevel = 0 --满级
self.onLevelChangeFn = nil --当等级改变时
self.onMaxLevelFn = nil --当最高级时
self.upSound = "dontstarve/wilson/equip_item_gold" --升级音效
end, nil, {
current = oncurrent,
maxLevel = OnChanged
})
---初始配置
---@param initLevel number|nil 初始等级
---@param maxLevel number 最高级
---@param onLevelChangeFn function|nil 当等级改变时,(inst,doer,count,isLoading)
---@param onMaxLevelFn function|nil 当最高级时,(inst,isLoading)
function Upgrade:Configure(initLevel, maxLevel, onLevelChangeFn, onMaxLevelFn)
self.initLevel = initLevel or self.initLevel
self.maxLevel = maxLevel or self.maxLevel
self.current = self.initLevel
self.onMaxLevelFn = onMaxLevelFn
self.onLevelChangeFn = onLevelChangeFn
end
function Upgrade:Upgrade(doer, count)
if count > 0 and self.current >= self.maxLevel then
return false, "MAX_LEVEL" --不应该发生,升级前应该判断标签
elseif count < 0 and self.current <= self.initLevel then
return false, "MIN_LEVEL"
end
count = count or 1
self.current = math.min(self.current + count, self.maxLevel) --虽然这里判断了,但是主要判断应该在调用之前,因为同时也涉及到物品的消耗数量
if self.onLevelChangeFn then
self.onLevelChangeFn(self.inst, doer, count, false)
end
if self.onMaxLevelFn and self.current >= self.maxLevel then
self.onMaxLevelFn(self.inst, false)
end
if self.upSound then
if doer and doer.SoundEmitter then
doer.SoundEmitter:PlaySound(self.upSound)
elseif self.inst.SoundEmitter then
self.inst.SoundEmitter:PlaySound(self.upSound)
end
end
return true
end
function Upgrade:GetNeed()
return self.maxLevel - self.current
end
function Upgrade:GetPercent()
return self.current / self.maxLevel
end
function Upgrade:IsFull()
return self.current >= self.maxLevel
end
function Upgrade:OnSave()
return {
current = self.current
}
end
function Upgrade:OnLoad(data)
if not data then return end
if data.current then
self.current = data.current
if self.current > self.initLevel then
self.inst:DoTaskInTime(0, function() --一般初始化都需要等其他东西加载后
if self.onLevelChangeFn then
self.onLevelChangeFn(self.inst, nil, self.current, true)
end
if self.current >= self.maxLevel and self.onMaxLevelFn then
self.onMaxLevelFn(self.inst, true)
end
end)
end
end
end
return Upgrade
- 组件副本
-- scripts/components/upt_upgrade_replica.lua
local componentPre = debug.getinfo(1, 'S').source:match("([^/]+)_upgrade_replica%.lua$") --当前文件前缀
local componentName = componentPre .. "_upgrade"
local Upgrade = Class(function(self, inst)
self.inst = inst
self.current = net_smallbyte(inst.GUID, componentName .. ".current") --[0..63]
end)
function Upgrade:SetLevel(level)
self.current:set(level)
end
function Upgrade:GetLevel()
return self.current:value()
end
return Upgrade
2. 使用方法
- 为可升级对象添加upt_upgrade组件,并且调用Configure方法配置,可配置的数据有:
- 初始等级
- 满级等级
- 当等级改变时调用的函数
- 当满级时的调用的函数
- 创建带有升级逻辑的Actions,在函数中调用升级组件的Upgrade方法。
- 定义AddComponentAction,设置触发升级动作的条件。
3. 使用案例

这是一个用木头升级万物的例子,初始等级为0级,满级为20级,鼠标移动到对象上可查看当前等级。
浙公网安备 33010602011771号