这个等级不是附魔等级,而是能够附魔所需要的经验等级.所以你只能随机到普通附魔.
如果开启treasures,那么宝藏附魔也能够被随机到.
一定有一把铁剑,但它耐久值是从125~250之间随机的.
值得一提的是这里的附加值并不能作为工具的附加值(也就是damage),所以如果要给工具设置damage,必须靠set_damage.
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:"a",Lore:["b"]}}"
- }
- ]
- }
- ]
- }
- ]
- }
复制代码- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:a,Lore:[b]}}"
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
两个是一样的,都是名为a,信息为b的石头.只是如果你在其中使用了需要转义的字符必须使用转义符.
这里的tag其实也支持自定义NBT
比如我加了一个对原版无任何影响的NBT:a
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:a,Lore:[b]},a:1}"
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
刷出来的结果:
如果使用
- /testfor @e[type=Item,c=1] {Item:{tag:{a:1}}}
复制代码
该自定义NBT的物品可以被检测.
Condition 1 实体死亡/实体分数
在了解Condition之前需要知道下面三个选择器:
this、killer和killer_player
this代表附上Loottable的实体,也就是死亡的实体;
killer就是杀死该实体的实体,不只是玩家;
killer_player必须是玩家.
(在Condition中不提供图片演示) (主要是条件不好模拟出来← ←)
┕ entity(字符串):选择器,选择实体
┕ properties(复合):满足条件
┕ on_fire(布尔):选择的实体是否着火
下面通过这个Condition来演示Condition三种情况
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:a,Lore:[b]}}"
- }
- ]
- }
- ],
- "conditions": [
- {
- "condition": "minecraft:entity_properties",
- "entity": "this",
- "properties": {
- "minecraft:on_fire": true
- }
- }
- ]
- }
- ]
- }
复制代码这个conditions条件列表在A Pool下,控制该随机池的调用
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:a,Lore:[b]}}"
- }
- ],
- "conditions": [
- {
- "condition": "minecraft:entity_properties",
- "entity": "killer",
- "properties": {
- "minecraft:on_fire": true
- }
- }
- ]
- }
- ]
- }
- ]
- }
复制代码 这个conditions条件列表在A Entry下,控制该项目的调用
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{display:{Name:a,Lore:[b]}}",
- "conditions": [
- {
- "condition": "minecraft:entity_properties",
- "entity": "killer_player",
- "properties": {
- "minecraft:on_fire": true
- }
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
这个conditions条件列表在A Function下,控制该功能的使用
回到这个Condition的写法上,on_fire填true或false就是判定是不是着火
entity后面只能填之前说的三个选择器.如果on_fire填true,那么分别判定该实体、击杀该实体的实体和击杀该实体的玩家是不是着火的,如果着火就调用条件列表的父级.
┕ entity(字符串):选择器,选择实体
┕ scores(复合):满足分数
┕ A score(整型):一个具体分数,把'A score'改成计分板名.
┕ A score(复合):一个范围分数,把'A score'改成计分板名.
┕ min(整型):值域中最小值
┕ min(整型):值域中最大值
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:cobblestone",
- "weight": 1,
- "conditions": [
- {
- "condition": "minecraft:entity_scores",
- "entity": "killer_player",
- "scores": {
- "b": 1,
- "a": {
- "min": 5,
- "max": 10
- }
- }
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
满足的条件就是b计分板分数=1,a计分板分数在5和10之间(包括5和10)
Condition 2 被玩家杀死
┕ inverse(布尔):是否反向选择,判断不是被玩家杀死的
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:cobblestone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:furnace_smelt",
- "conditions": [
- {
- "condition": "minecraft:killed_by_player",
- "inverse": false
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
判断是被玩家杀死的.
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:cobblestone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:furnace_smelt",
- "conditions": [
- {
- "condition": "minecraft:killed_by_player",
- "inverse": true
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
判断不是被玩家杀死得,包括被其他实体杀死和自然死亡(摔死淹死等)
Condition 3 二次随机点数
┕ chance(浮点):此处填写一个0.0~1.0的数值(叫做点数).系统会生成一个0.0~1.0的随机数,与这里填写的数值比较.若小于该数值则成功.
比如填写1.0,那么必然成功.如果填写0.8,只有80%的概率.
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "quality": 3,
- "conditions": [
- {
- "condition": "minecraft:random_chance",
- "chance": 0.5
- }
- ]
- },
- {
- "type": "item",
- "name": "minecraft:diamond",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
尽管随机的权重为1,但只有50%几率得到石头
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:furnace_smelt",
- "conditions": [
- {
- "condition": "minecraft:random_chance",
- "chance": 0.5
- }
- ]
- }
- ]
- },
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
在这个实例里,首先有一个石头,虽然权重为1,但只有50%几率获得.
另外一个石头权重也是1.
因此我们可以算算获得石头的概率:
没有石头-首先抽中了第一个石头,也就是50%概率.接着点数大于0.5,又是50%概率,所以几率为25%.
1个-第一种情况是抽中第一个石头,点数没有大于0.5,25%几率;第二种情况是抽中了第二个石头,因为是必得,所以总的来说50%几率;加起来75%几率.
之所以叫该条件为稳定二次随机,是因为在一个项目下该条件点数可以结合权重实现更精确的概率微调;
如果该条件和一个随机池结合,那么随机池也是靠点数来调用;同理一个功能也是如此.
Condition 3 二次随机(抢夺)
- random_chance_with_looting抢夺影响判定
┕ chance(浮点):此处填写一个0.0~1.0的数值(叫做基础点数).
┕ looting_multiplier:(浮点):抢夺等级的乘数
系统会生成一个0.0~1.0的随机数,与下面公式算出来的值比较.若小于则成功.
chance + looting_level * looting_multiplier
也就是:基础点数+抢夺附魔等级*等级乘数
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:furnace_smelt",
- "conditions": [
- {
- "condition": "minecraft:random_chance_with_looting",
- "chance": 0.2,
- "looting_multiplier": 0.1
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
此处使用抢夺3附魔,掉落石头的概率就是:0.2+3*0.1=0.5
该condition也是稳定二次随机,相比之下引入了抢夺.
Entry 1 物品
作为随机项目,主要是针对物品。
事实上在前面我们已经举了很多例子,现在我们需要用上所有Entry中使用的结构来完整的呈现一个物品列表:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "quality": 1,
- "functions": [
- {
- "function": "minecraft: set_count",
- "count": {
- "min": 0,
- "max": 1
- }
- }
- ],
- "conditions": [
- {
- "condition": "minecraft: killed_by_player"
- }
- ]
- },
- {
- "type": "item",
- "name": "minecraft: diamond",
- "weight": 1,
- "quality": 3,
- "functions": [
- {
- "function": "minecraft:set_count",
- "count": {
- "min": 0,
- "max": 1
- }
- }
- ],
- "conditions": [
- {
- "condition": "minecraft:killed_by_player"
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
下面来分析这个Loottable
首先只有一个随机池,随机池只会选择一次物品;
物品列表两个物品,一个是石头,一个是钻石;
石头的权重为1,权重增值为1;钻石权重为1,权重增值为3(也就是当你幸运2时,石头真实权重为3,钻石却变成了7)
两者获得条件都是被玩家击杀,而且两者都有50%数量为0(也就是无).
Entry 2 空
将项目设为空,可以帮助我们初步的稳定概率,所以可以说属于是稳定一次随机.
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "empty",
- "weight": 1
- },
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
这个实例里,我们抽中石头的几率只是50%,另外50%为空.
空,是Entry中一个补位,用于控制随机,可以结合后面的内容稳定概率.
比如实体如果要让物品随机掉落,请注意控制Entry适当为空的几率,否则将必然掉落物品;
Entry 3 随机概率计算
为了平衡物品,难免必须用到概率计算,在学习计算之前,再来总结总结一次随机和二次随机.
也许你还对之前提到的一次随机,二次随机不了解,下面就来总结总结:
是对项目列表中项目的第一次随机,也就是靠真实权重来判定的随机:
真实权重=(权重+权重增值*幸运值)
是进一步对该项目的取舍随机,例如Function中set_count,和Condition中的random_chance/random_chance.
下面进入正式计算阶段,来看两个例子:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:stone",
- "weight": 1,
- "quality": 3,
- "conditions": [
- {
- "condition": "minecraft:random_chance",
- "chance": 0.5
- }
- ]
- },
- {
- "type": "item",
- "name": "minecraft:diamond",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码 这个就是之前Condition3中的例子,引入了权重增值.
如果你要计算抽中一个项目的概率,你可以使用下面的方法:
先来看一次随机,石头权重就是=(1+3*幸运值),而钻石始终为1,
那么一次随机中石头概率为(1+3*幸运值)/(2+3*幸运值)
接着来看二次随机,此处二次随机是随机点数,所以石头只有50%概率不为空.
那么总共石头的概率就是(1+3*幸运值)/(4+6*幸运值).
公式:
一个项目的真实权重=(该项目权重+该权重增值*幸运值)
random_chance = 随机点数【随机点数】或者(基础点数+抢夺附魔等级*等级乘数)【抢夺判定】
一个项目的概率=(一个项目真实权重/项目列表真实权重总和)* random_chance * (1-set_count中选中0的概率)
*注解:set_count选中0的概率靠这样计算:例如min:0,max:10,那么一共可能有11种数量结果,那么选中0的概率就是1/11.
当然,这种方法也可以用于三次随机(function中的condition),也就是继续在后面乘上随机点数:
带功能的一个项目的概率=(一个项目真实权重/项目列表真实权重总和)* random_chance【对于Entry】 * (1-set_count中选中0的概率) * random_chance【对于Function】
公式套用前面的,只是略微改动:(设这个数量为n)
一个项目的概率=(一个项目真实权重/项目列表真实权重总和)* random_chance * (中选中n的概率)
带功能的一个项目的概率=(一个项目真实权重/项目列表真实权重总和)* random_chance【对于Entry】 * (set_count中选中n的概率) * random_chance【对于Function】
Pool 随机抽取原理
在一个随机池中,只能有一个项目列表,每次从项目列表中抽取一个项目.
roll的次数就是抽取次数.
而项目列表中项目的weight和quality决定了该项目抽到的几率.
结合function和condition,也许抽取的项目为空,或者貌似多个项目;或者下面讲到调用loottable,事实上都是一个项目.
一个项目≠一个物品,一个项目只是抽取的结果.
(每次抽取的项目也许包含n个子项目,也可能继续随机抽取)
所以打破该误区之后,将会在下面loottable一节中运用这种概念来完成更复杂的随机列表.
Pool 随机列表滚动值
你可以理解为一个骰子,每滚动一次最后随机抽取一个点数.
当然滚动值不是这个滚动所得点数,也不是权重,更不能理解成为项目中物品数量翻多少倍
滚动值就是投掷骰子的次数,近似的理解为抽取多少项目(可重复),
准确来说是抽取项目列表中一个项目的次数.
rolls:1
就是抽取一次(滚动值默认为0)
rolls:10
就是抽取十次
bonus_rolls就是幸运值对滚动值的影响
最终真实滚动值实际上是向下取整(rolls+bonus_rolls*幸运值)
rolls:3 本来抽取3次
bonus_rolls:1.5之后
如果幸运值=1,就是抽取4次。如果幸运值=2,就是抽取6次。
Loottable嵌套
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:b/a",
- "weight": 1
- },
- {
- "type": "loot_table",
- "name": "test:a",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
嵌套中调用的loottable分别是命名空间test中文件夹b的a和a
两者随机到的权重相同
从逻辑上使结构更清晰
从技术上避免了冗杂的填写物品,可以将多物品进行打包(建立一个loottable)操作
比如loottable1嵌套了一个loottable2
我们知道了loottable选取一个项目的步骤是:
Lootable→所有Pools→选取Entry
那么嵌套一个loottable,事实上就是将这个过程*2
Lootable1→所有loottable1的Pools→选取loottable2→所有loottable2的Pools→选取Entry
Loottable循环嵌套
既然Loottable支持嵌套,那么如果Loottable1套着Loottable2,而Loottable2又有Loottable1会怎么样呢:
以上所述的Loottable2都是:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:loottable1",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
有三种情况
如果Loottable2作为项目,物品在另一个池中
Loottable1:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:loottable2",
- "weight": 1
- }
- ]
- },
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:wool",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
那么Loottable1无限调用,直到溢出:(实体掉落未尝试,也许会崩,也许什么事也没发生)
如果项目和调用Loottable在同一个池中
Loottable1:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:loottable2",
- "weight": 1
- },
- {
- "type": "item",
- "name": "minecraft:wool",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
那么在嵌套调用过程中,如果抽中了物品将会停止无限循环
也就是最后只有一个物品
Loottable1:
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "item",
- "name": "minecraft:chest",
- "weight": 1,
- "functions": [
- {
- "function": "minecraft:set_nbt",
- "tag": "{LootTable:test:loottable2}"
- }
- ]
- }
- ]
- }
- ]
- }
复制代码
那么容器会不断调用Loottable1,也就是无限箱子
Loottable与多个池与溢出
Pool在LootTable中是并列的,每个Pool必然会选中(若无条件)
Entry在Pool中是独立的,只能选中一个
多个池支持让Loottable更丰富
嵌套进入多个池,能使一个Loottable调用多个Loottable
- {
- "pools": [
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:b/a",
- "weight": 1
- },
- {
- "type": "loot_table",
- "name": "test:loottable3",
- "weight": 1
- }
- ]
- },
- {
- "rolls": 1,
- "entries": [
- {
- "type": "loot_table",
- "name": "test:loottable3",
- "weight": 1
- }
- ]
- }
- ]
- }
复制代码
这样该loottable就调用了loottable2和3.
而如果Loottable1中有n个随机池,每个随机池中都有必然选中的Entry,且该项目是Loottable2,Loottable2中,那么就有了一个溢出的问题。
在前面的问题中,loottable1中n个随机池都调用loottable,如果lootable2中项目是m个,
那么总物品数量≥mn个,如果总物品超过容器容量上限,那么保留的物品有什么原则?
溢出后的物品只取Lootable中从上至下的顺序所选取的项目的物品.
因为每次选择项目时给其中每个物品都分配一个随机的slot,
从上至下顺序是读取json的顺序,那么每次读取一个项目,都有一个上面的分配过程,直到分配物品超过随机slot.
在写loottable中一定要留意父子级的调用造成的溢出给随机物品带来的影响,尤其是在一个loottable中出现总物品较多的情况下.