基于原版冷却组件实现动态冷却
这期篇幅较短,算是一个小技巧。
use_cooldown
是1.21.2加入的组件。它可以让物品在被如consumable组件消耗后进入一段冷却,就像末影珍珠一样。在视觉效果上能够有明显的提示。
不过它的行为比较古板,不是特别好用:
该组件只能指定固定的冷却的时间,不能动态变化,也不能在触发冷却之后缩减冷却的时间。
不过结合宏,我们可以在一定程度上实现动态冷却时间。
来看这个实例:
题目背景
某物品有一个右键技能(使用consumable组件实现),拥有两次使用次数,冷却各自独立。我们如果需要使用原版的冷却组件实现冷却效果,需要在该物品的第二次使用次数结束后,让物品进入冷却,冷却时间为第一次使用到现在剩余的冷却时间。
计时计算
我们使用两个计时器计分板,分别计算两次使用次数的冷却时间;
另立第三个计分板,用来综合两个计时器的最终冷却时间,然后将这个值替换到物品的冷却组件上。
按照一般的思路,这个综合计分板应该比较两个冷却计分板的数值,然后取较小的一个。
但是注意:在物品第二次使用后就会立即进入冷却,因此我们需要在第二次使用前开始计算预估的冷却时间。
分类讨论:
两个计分板均为0:总计分板为0,物品使用后冷却值为0,可以再次使用;
有一个为0:此时物品仍可使用,但在使用前,我们需要模拟使用后的情况,也就是置0的计分板被刷新为冷却时间,此时不为0的那个计分板变成了较小的那一个,因此,此时我们要取非0的那一个。 两个都不为0:物品不可使用,不关心使用那一个值。
综合来看,为了避免分类判断,我们可以直接把总计分板设为两个独立计分板中较大的那一个。
推广到三个以及更多计分板的情况,我们应该将总计分板设为第二小的计分板值。
不过需要注意,use_cooldown
组件不支持设置0冷却值,同时为了防止误触考虑,我们可以设定一个基础冷却值,比如说10刻(0.5秒),将这个值加到总计分板的最终值上。
物品修饰
接下来,我们需要把计分板的值复制到物品的冷却组件上。
首先想到,可以使用物品修饰器直接修改物品组件;不过物品修饰器不支持动态设置值;
那么,可以使用第一期提到的内联物品修饰器,将物品修饰器内联在函数里,再使用宏设置动态参数。
以下是相关函数示例:
trident:spear/cooldown_set
:
execute store result storage spear cooldown float 0.05 run scoreboard players get @s spear_cooldown
execute if predicate trident:spear/main run function trident:spear/modify with storage minecraft:spear
trident:spear/modify
:
$item modify entity @s weapon.mainhand {\
"function": "set_components",\
"components": {\
"use_cooldown": {\
"seconds": $(cooldown),\
"cooldown_group": "spear"\
}\
}\
}
细节处理
但是,我们也不能高频的替换物品。损耗性能不说,还会使玩家手持物品的动画变得奇怪。
我们可以把consumable组件的消耗时间变为2tick,当检测到使用物品时,对物品的冷却时间进行替换。
在实践的过程中,发现如果使用进度检测使用并直接在进度奖励函数中调用替换函数,会导致物品无法被消耗,因此在进度检测中,改为给玩家上一个标记,在tick函数中检测这个标记进行替换,就正常了。