游戏中会有很多数值时刻发生着变化,比如角色的攻击力、移速等会因为各种 buff 发生改变,这些 buff 的来源也可能有很多,比如自身技能、敌人技能或者队友给你加的 buff 等等,这些 buff 还可以叠加,持续时间结束之后需要移除。这些对基础数值的修改称为 modifier
。
为了完成 modifier
的管理,饥荒 mod 为我们提供了一个思路。
SourceModifierList
饥荒中提供了一个类 SourceModifierList
用来管理这样的数值修改,先来看看怎么用的。
饥荒中所有需要战斗的实体都依赖于一个组件 combat
,combat
为角色提供了攻击力,基本公式为:攻击力 = 基础攻击 * 攻击系数。
攻击系数就是一个 SourceModifierList
:
-- self 是 combat 组件,self.inst 是 combat 挂载的对象
self. = SourceModifierList
默认的修改值为 1,修改方法是所有 modifier
相乘(即基础攻击力 * 1)。
添加 modifier
角色吃下电羊果冻后,使角色攻击力乘以 1.5 倍,这时就需要添加一个 modifier
-- food 是电羊果冻,用于移除时的索引
inst...:
移除 modifier
电羊果冻持续时间结束后,移除对应的 modifier,角色攻击力就会恢复正常
inst...:
计算攻击力
计算攻击力时,只需要调用 Get()
方法
实现
以下代码都只保留关键结构,省略了很多细节
SourceModifierList
的实现也不复杂,维护了这几个私有变量:
_modifiers
:内部用一个字典保存每个来源(source)对应的 modifier,当然一个 source 可能对应多个 modifier,所以每个 source 又对应一个字典,字典中再用字符串 key 标识不同的 modifier。_modifier
:保存最终计算出的修改值_fn
:计算修改值的函数,默认为两两相乘。也就是最终的_modifier
是由_modifiers
中的所有数值相乘得到的。_base
:基值,默认为 1。如果_fn
是加法就应该设为 0。
SourceModifierList = Class
SourceModifierList. =
SourceModifierList. =
SourceModifierList. =
SetModifier
时,把 modifier 存入字典,然后重新计算 _modifier
结果。
重新计算(RecalculateModifier
)也很简单,调用 _fn
遍历所有的 modifier 计算一遍即可。
local
RemoveModifier
把对应项从 _modifiers
字典移除,再重新计算 _modifier
。
-- Key is optional if you want to remove the entire source
计算 _modifier
值是在添加和移除 modifier 时执行的,因此调用 Get()
时,只是简单地返回 _modifier
而已:
以上就是 SourceModifier
的基本原理,完全可以应用在其他游戏中。
饥荒中还实现了更多实用的功能,比如
- 计算所有相同
source
的 modifier 值 - 计算所有相同
key
的 modifier 值 source
对象销毁时,自动调用RemoveModifier
这些可以根据游戏实际需求选择实现。