⭐✔️
本帖最后由 贰逼 于 2018-8-29 22:26 编辑

Loottable(可抢夺物品列表)是1.9+中的一个新特性,主要靠调用外置json文件实现对物品奖励获取的随机.
第二章内将会向各位介绍Loottable中的实例与详解

Chm版本:http://pan.baidu.com/s/1c1U4804 (若.chm遇到问题下载压缩文件)
全部章节总索引
上一章 结构与标签
下一章 技术性提示



2021.12 数据,可能有更多内容Loottable(可抢夺物品列表)是1.9+中的一个新特性,主要靠调用外置json文件实现对物品奖励获取的随机.
第二章内将会向各位介绍Loottable中的实例与详解


Chm版本:http://pan.baidu.com/s/1c1U4804 (若.chm遇到问题下载压缩文件)
全部章节总索引
上一章 结构与标签下一章 技术性提示



人生第一个Loottable
看了之前结构与标签的基本介绍,我们现在就可以写一个简单的Loottable了:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1
  10.     }
  11.    ]
  12.   }
  13.     ]
  14. }
没错,这就是最简单的一个Loottable,下面我们来逐步分析一下这个Loottable讲了什么.


首先随机池列表中只有一个随机池,这个随机池里的项目列表中只有一个项目——石头.
唯一的随机池只从它的项目列表中选取一次物品,并且项目列表中唯一的项目石头的权重为1.
所以实际效果就是该Loottable的结果必然是一个石头.


建立Loottable文件夹
如果我们要在游戏中调用Loottable,我们先必须学会如何建立一个Loottable文件夹,以便调用Loottable
首先我们需要找到存档的文件夹

进入存档文件中的data文件夹

新建一个名为“loot_tables”的文件夹



在其中创建一个子文件夹,在loot_tables文件夹里一个子文件夹就代表一个命名空间(此时命名空间为“test”)



在命名空间内新建一个json文件,并粘贴之前的Loottable作为内容.该json文件名是Loottable的名字(此时名字为“a”)
当然也可以在这个命名空间再建子文件夹,子文件夹中建立Loottable,也是允许的.


新建json文件可以靠代码编写软件,也可以直接新建一个文本文档并将.txt改成.json.


json可以直接靠打开方式选择记事本打开.


调用Loottable
进入该存档,接下来介绍如何调用Loottable


首先我们要知道Loottable路径表达式怎么写.
标准写法:
[命名空间]:[Loottable名] 或者 [命名空间]:[子文件夹名]/[Loottable名]

例如刚才的示例:
test:a

就是路径表达式.(当然这是第一种写法)
值得一提的是如果没有命名空间,默认命名空间就是minecraft.例如entities/creeper,代表默认的爬行者掉落物.


接下来我们可以靠NBT调用Loottable了.
有两个NBT:LootTable(string)和DeathLootTable(string)
第一个LootTable标签用于大部分容器,而第二个DeathLootTable标签用于实体.
后面的string处需要填写的就是Loottable路径表达式.

代码:

  1. /setblock ~ ~ ~ minecraft:chest 附加值 模式 {LootTable:"test:a"}

代码:

  1. /summon Zombie ~ ~ ~ {DeathLootTable:"test:a"}


Function 1 随机附魔/随机等级附魔/烤熟的物品
  • enchant_randomly随机附魔
    ┕ enchantments(列表):能够附上的魔 (默认为能与对应物品匹配的附魔)

代码:

  1. <blockquote>{

随机结果预览这个标签不会规定附魔的等级,随机的等级范围也只是该附魔的最大等级(在非NBT修改的情况下)
  • enchant_with_levels随机附魔的等级
    ┕ treasure(布尔):是否能随机到宝藏附魔(例如冰霜行者和修理)    ┕ levels(整型):随机附魔的等级    ┕ levels(列表):随机附魔的等级范围  └ min(整型):随机附魔的最小级  └ max(整型):随机附魔的最大等级

代码:

  1. <blockquote>{

结果预览这个等级不是附魔等级,而是能够附魔所需要的经验等级.所以你只能随机到普通附魔.如果开启treasures,那么宝藏附魔也能够被随机到.
  • furnace_smelt
无子项目,内容:将被烤熟的物品

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:fish",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:furnace_smelt"
  13.    }
  14.   ]
  15.     }
  16.    ]
  17.   }
  18.     ]
  19. }

所有能被冶炼/烤熟的物品都能被这个功能涉及.(例如土豆或者原木或者钻石原矿)
Function 2 抢夺附魔数量影响/物品属性
  • looting_enchant数量影响(适用于实体)
    ┕ limit(整型):抢夺附魔后额外最大掉落的数量    ┕ count(整型):抢夺附魔后额外掉落的数量    ┕ count(列表):抢夺附魔后额外掉落的数量范围  └ min(整型):抢夺附魔后掉落最小的数量  └ max(整型):抢夺附魔后掉落最大的数量

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:wool",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:looting_enchant",
  13.     "count": 1,
  14.     "limit": 3
  15.    }
  16.   ]
  17.     }
  18.    ]
  19.   }
  20.     ]
  21. }

掉落羊毛,初始1个,抢夺后额外1个,最大3个.

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:wool",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:looting_enchant",
  13.     "count": {
  14.   "min": 3,
  15.   "max": 5
  16.     }
  17.    }
  18.   ]
  19.     }
  20.    ]
  21.   }
  22.     ]
  23. }

掉落羊毛,初始1个,抢夺后额外3~5个,没有限制.


  • set_attributes物品属性修改器

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:diamond_sword",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_attributes",
  13.     "modifiers": [
  14.   {
  15.    "attribute": "generic.attackDamage",
  16.    "name": "Damage",
  17.    "amount": {
  18.     "min": 1.0,
  19.     "max": 1.5
  20.    },
  21.    "operation": "addition",
  22.    "slot": [
  23.     "mainhand",
  24.     "offhand"
  25.    ]"id": "00000000-0000-0001-0000-000000000001"
  26.   }
  27.     ]
  28.    }
  29.   ]
  30.     }
  31.    ]
  32.   }
  33.     ]
  34. }

NBT和具体效果就不讲解了,和原来的属性NBT相同,除了amount增加了最小和最大的选项.(详情站内本版内搜索物品属性)


Function 3 数量/工具损害值/物品附加值
  • set_count数量
    ┕ count(整型):物品的具体数量    ┕ count(列表):物品的随机数量范围  └ min(整型):物品最小的数量  └ max(整型):物品最大的数量


代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_count",
  13.     "count": 10
  14.    }
  15.   ]
  16.     }
  17.    ]
  18.   }
  19.     ]
  20. }


也就是一定产出十个石头(排列不一定整齐)

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_count",
  13.     "count": {
  14.   "min": 10,
  15.   "max": 20
  16.     }
  17.    }
  18.   ]
  19.     }
  20.    ]
  21.   }
  22.     ]
  23. }

也就是一定产出10~20个石头(排列不一定整齐)图中一共14个
  • set_damage损害
    ┕ damage(浮点):物品(工具)的剩余耐久的比率.也就是剩余的耐久/最大耐久.(1.0就是是没有损害,0.0就是没耐久了)    ┕ damage(列表):剩余耐久的比率的范围  └ min(浮点):剩余耐久比率最小值  └ max(浮点):剩余耐久比率最大值


代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:iron_sword",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_damage",
  13.     "damage": {
  14.   "min": 0.5,
  15.   "max": 1
  16.     }
  17.    }
  18.   ]
  19.     }
  20.    ]
  21.   }
  22.     ]
  23. }

一定有一把铁剑,但它耐久值是从125~250之间随机的.
  • set_data物品附加值
    ┕ data(整型):物品(非工具)的附加值    ┕ data(列表):附加值的范围  └ min(整型):附加值的最小值  └ max(整型):附加值的最大值


代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:wool",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_data",
  13.     "data": {
  14.   "min": 0,
  15.   "max": 15
  16.     }
  17.    }
  18.   ]
  19.     }
  20.    ]
  21.   }
  22.     ]
  23. }


这个就是随机一个颜色的羊毛(附加值0~15)
值得一提的是这里的附加值并不能作为工具的附加值(也就是damage),所以如果要给工具设置damage,必须靠set_damage.
Function 4 NBT和自定义NBT
  • set_nbt数据标签
    ┕ tag(字符串):物品的tag标签后的内容

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:"a",Lore:["b"]}}"
  14.    }
  15.   ]
  16.     }
  17.    ]
  18.   }
  19.     ]
  20. }

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:}}"
  14.    }
  15.   ]
  16.     }
  17.    ]
  18.   }
  19.     ]
  20. }

两个是一样的,都是名为a,信息为b的石头.只是如果你在其中使用了需要转义的字符必须使用转义符.
这里的tag其实也支持自定义NBT比如我加了一个对原版无任何影响的NBT:a

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:},a:1}"
  14.    }
  15.   ]
  16.     }
  17.    ]
  18.   }
  19.     ]
  20. }

刷出来的结果:

如果使用


代码:

  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死亡条件

    ┕ entity(字符串):选择器,选择实体    ┕ properties(复合):满足条件  ┕ on_fire(布尔):选择的实体是否着火下面通过这个Condition来演示Condition三种情况

代码:


  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:}}"
  14.    }
  15.   ]
  16.     }
  17.    ],
  18.    "conditions": [
  19.     {
  20.   "condition": "minecraft:entity_properties",
  21.   "entity": "this",
  22.   "properties": {
  23.    "minecraft:on_fire": true
  24.   }
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }
这个conditions条件列表在A Pool下,控制该随机池的调用

代码:


  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:}}"
  14.    }
  15.   ],
  16.   "conditions": [
  17.    {
  18.     "condition": "minecraft:entity_properties",
  19.     "entity": "killer",
  20.     "properties": {
  21.   "minecraft:on_fire": true
  22.     }
  23.    }
  24.   ]
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }
这个conditions条件列表在A Entry下,控制该项目的调用

代码:


  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:}}",
  14.     "conditions": [
  15.   {
  16.    "condition": "minecraft:entity_properties",
  17.    "entity": "killer_player",
  18.    "properties": {
  19.     "minecraft:on_fire": true
  20.    }
  21.   }
  22.     ]
  23.    }
  24.   ]
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }

这个conditions条件列表在A Function下,控制该功能的使用回到这个Condition的写法上,on_fire填true或false就是判定是不是着火entity后面只能填之前说的三个选择器.如果on_fire填true,那么分别判定该实体、击杀该实体的实体和击杀该实体的玩家是不是着火的,如果着火就调用条件列表的父级.
  • entity_scores实体分数
    ┕ entity(字符串):选择器,选择实体    ┕ scores(复合):满足分数    ┕ A score(整型):一个具体分数,把'A score'改成计分板名.    ┕ A score(复合):一个范围分数,把'A score'改成计分板名.  ┕ min(整型):值域中最小值  ┕ min(整型):值域中最大值

代码:


  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:cobblestone",
  9.   "weight": 1,
  10.   "conditions": [
  11.    {
  12.     "condition": "minecraft:entity_scores",
  13.     "entity": "killer_player",
  14.     "scores": {
  15.   "b": 1,
  16.   "a": {
  17.    "min": 5,
  18.    "max": 10
  19.   }
  20.     }
  21.    }
  22.   ]
  23.     }
  24.    ]
  25.   }
  26.     ]
  27. }

满足的条件就是b计分板分数=1,a计分板分数在5和10之间(包括5和10)
Condition 2 被玩家杀死
  • killed_by_player被玩家杀死

    ┕ inverse(布尔):是否反向选择,判断不是被玩家杀死的

代码:


  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:cobblestone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:furnace_smelt",
  13.     "conditions": [
  14.   {
  15.    "condition": "minecraft:killed_by_player",
  16.    "inverse": false
  17.   }
  18.     ]
  19.    }
  20.   ]
  21.     }
  22.    ]
  23.   }
  24.     ]
  25. }

判断是被玩家杀死的.

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:cobblestone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:furnace_smelt",
  13.     "conditions": [
  14.   {
  15.    "condition": "minecraft:killed_by_player",
  16.    "inverse": true
  17.   }
  18.     ]
  19.    }
  20.   ]
  21.     }
  22.    ]
  23.   }
  24.     ]
  25. }

判断不是被玩家杀死得,包括被其他实体杀死和自然死亡(摔死淹死等)


Condition 3 二次随机点数
  • random_chance随机几率

    ┕ chance(浮点):此处填写一个0.0~1.0的数值(叫做点数).系统会生成一个0.0~1.0的随机数,与这里填写的数值比较.若小于该数值则成功.比如填写1.0,那么必然成功.如果填写0.8,只有80%的概率.

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "quality": 3,
  11.   "conditions": [
  12.    {
  13.     "condition": "minecraft:random_chance",
  14.     "chance": 0.5
  15.    }
  16.   ]
  17.     },
  18.     {
  19.   "type": "item",
  20.   "name": "minecraft:diamond",
  21.   "weight": 1
  22.     }
  23.    ]
  24.   }
  25.     ]
  26. }

尽管随机的权重为1,但只有50%几率得到石头

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:furnace_smelt",
  13.     "conditions": [
  14.   {
  15.    "condition": "minecraft:random_chance",
  16.    "chance": 0.5
  17.   }
  18.     ]
  19.    }
  20.   ]
  21.     },
  22.     {
  23.   "type": "item",
  24.   "name": "minecraft:stone",
  25.   "weight": 1
  26.     }
  27.    ]
  28.   }
  29.     ]
  30. }

在这个实例里,首先有一个石头,虽然权重为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



也就是:基础点数+抢夺附魔等级*等级乘数


代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:furnace_smelt",
  13.     "conditions": [
  14.   {
  15.    "condition": "minecraft:random_chance_with_looting",
  16.    "chance": 0.2,
  17.    "looting_multiplier": 0.1
  18.   }
  19.     ]
  20.    }
  21.   ]
  22.     }
  23.    ]
  24.   }
  25.     ]
  26. }

此处使用抢夺3附魔,掉落石头的概率就是:0.2+3*0.1=0.5


该condition也是稳定二次随机,相比之下引入了抢夺.


Entry 1 物品
作为随机项目,主要是针对物品。
事实上在前面我们已经举了很多例子,现在我们需要用上所有Entry中使用的结构来完整的呈现一个物品列表:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "quality": 1,
  11.   "functions": [
  12.    {
  13.     "function": "minecraft: set_count",
  14.     "count": {
  15.   "min": 0,
  16.   "max": 1
  17.     }
  18.    }
  19.   ],
  20.   "conditions": [
  21.    {
  22.     "condition": "minecraft: killed_by_player"
  23.    }
  24.   ]
  25.     },
  26.     {
  27.   "type": "item",
  28.   "name": "minecraft: diamond",
  29.   "weight": 1,
  30.   "quality": 3,
  31.   "functions": [
  32.    {
  33.     "function": "minecraft:set_count",
  34.     "count": {
  35.   "min": 0,
  36.   "max": 1
  37.     }
  38.    }
  39.   ],
  40.   "conditions": [
  41.    {
  42.     "condition": "minecraft:killed_by_player"
  43.    }
  44.   ]
  45.     }
  46.    ]
  47.   }
  48.     ]
  49. }

下面来分析这个Loottable
首先只有一个随机池,随机池只会选择一次物品;
物品列表两个物品,一个是石头,一个是钻石;
石头的权重为1,权重增值为1;钻石权重为1,权重增值为3(也就是当你幸运2时,石头真实权重为3,钻石却变成了7)
两者获得条件都是被玩家击杀,而且两者都有50%数量为0(也就是无).


Entry 2 空
将项目设为空,可以帮助我们初步的稳定概率,所以可以说属于是稳定一次随机.

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "empty",
  8.   "weight": 1
  9.     },
  10.     {
  11.   "type": "item",
  12.   "name": "minecraft:stone",
  13.   "weight": 1
  14.     }
  15.    ]
  16.   }
  17.     ]
  18. }

这个实例里,我们抽中石头的几率只是50%,另外50%为空.


空,是Entry中一个补位,用于控制随机,可以结合后面的内容稳定概率.
比如实体如果要让物品随机掉落,请注意控制Entry适当为空的几率,否则将必然掉落物品;


Entry 3 随机概率计算
为了平衡物品,难免必须用到概率计算,在学习计算之前,再来总结总结一次随机和二次随机.
也许你还对之前提到的一次随机,二次随机不了解,下面就来总结总结:
  • 一次随机
是对项目列表中项目的第一次随机,也就是靠真实权重来判定的随机:
真实权重=(权重+权重增值*幸运值)


  • 二次随机
是进一步对该项目的取舍随机,例如Function中set_count,和Condition中的random_chance/random_chance.


下面进入正式计算阶段,来看两个例子:
  • 抽中一个项目的概率

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:stone",
  9.   "weight": 1,
  10.   "quality": 3,
  11.   "conditions": [
  12.    {
  13.     "condition": "minecraft:random_chance",
  14.     "chance": 0.5
  15.    }
  16.   ]
  17.     },
  18.     {
  19.   "type": "item",
  20.   "name": "minecraft:diamond",
  21.   "weight": 1
  22.     }
  23.    ]
  24.   }
  25.     ]
  26. }
这个就是之前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嵌套
  • 一个标准嵌套实例

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "loot_table",
  8.   "name": "test:b/a",
  9.   "weight": 1
  10.     },
  11.     {
  12.   "type": "loot_table",
  13.   "name": "test:a",
  14.   "weight": 1
  15.     }
  16.    ]
  17.   }
  18.     ]
  19. }

嵌套中调用的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都是:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "loot_table",
  8.   "name": "test:loottable1",
  9.   "weight": 1
  10.     }
  11.    ]
  12.   }
  13.     ]
  14. }



有三种情况
  • 项目无限循环
如果Loottable2作为项目,物品在另一个池中
Loottable1:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "loot_table",
  8.   "name": "test:loottable2",
  9.   "weight": 1
  10.     }
  11.    ]
  12.   },
  13.   {
  14.    "rolls": 1,
  15.    "entries": [
  16.     {
  17.   "type": "item",
  18.   "name": "minecraft:wool",
  19.   "weight": 1
  20.     }
  21.    ]
  22.   }
  23.     ]
  24. }

那么Loottable1无限调用,直到溢出:(实体掉落未尝试,也许会崩,也许什么事也没发生)



  • 普通调用
如果项目和调用Loottable在同一个池中
Loottable1:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "loot_table",
  8.   "name": "test:loottable2",
  9.   "weight": 1
  10.     },
  11.     {
  12.   "type": "item",
  13.   "name": "minecraft:wool",
  14.   "weight": 1
  15.     }
  16.    ]
  17.   }
  18.     ]
  19. }

那么在嵌套调用过程中,如果抽中了物品将会停止无限循环
也就是最后只有一个物品

  • 容器
Loottable1:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:chest",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{LootTable:test:loottable2}"
  14.    }
  15.   ]
  16.     }
  17.    ]
  18.   }
  19.     ]
  20. }

那么容器会不断调用Loottable1,也就是无限箱子




Loottable与多个池与溢出
  • 多个池

Pool在LootTable中是并列的,每个Pool必然会选中(若无条件)
Entry在Pool中是独立的,只能选中一个
多个池支持让Loottable更丰富


  • Loottable嵌套与多个池
嵌套进入多个池,能使一个Loottable调用多个Loottable

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "loot_table",
  8.   "name": "test:b/a",
  9.   "weight": 1
  10.     },
  11.     {
  12.   "type": "loot_table",
  13.   "name": "test:loottable3",
  14.   "weight": 1
  15.     }
  16.    ]
  17.   },
  18.   {
  19.    "rolls": 1,
  20.    "entries": [
  21.     {
  22.   "type": "loot_table",
  23.   "name": "test:loottable3",
  24.   "weight": 1
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }

这样该loottable就调用了loottable2和3.


而如果Loottable1中有n个随机池,每个随机池中都有必然选中的Entry,且该项目是Loottable2,Loottable2中,那么就有了一个溢出的问题。


  • 溢出(实体掉落无此问题)
在前面的问题中,loottable1中n个随机池都调用loottable,如果lootable2中项目是m个,
那么总物品数量≥mn个,如果总物品超过容器容量上限,那么保留的物品有什么原则?
溢出后的物品只取Lootable中从上至下的顺序所选取的项目的物品.


因为每次选择项目时给其中每个物品都分配一个随机的slot,
从上至下顺序是读取json的顺序,那么每次读取一个项目,都有一个上面的分配过程,直到分配物品超过随机slot.


在写loottable中一定要留意父子级的调用造成的溢出给随机物品带来的影响,尤其是在一个loottable中出现总物品较多的情况下.

Loottable防溢出和分配物品
因为有溢出物品规则的存在,如果随机的物品总数大于了容器单元总数,所的物品仍旧不是随机的.


为了防止溢出,我们可以对Pools中随机池的总数,以及Pool中的Rolls进行控制,
首先我们需要检测是否存在溢出的可能:
Rolls总数=该Loottable或所有调用的底Loottable(最低级)的Rolls(Rolls_max)总数
如果一个Loottable的Rolls总数>容器单元总数,那么总有溢出的可能.


对于溢出,有两种方法分配物品:
1.将多个并列Pool中的Entry合并
2.减少Rolls次数





Loottable作为项目中物品的概率
计算概率是平衡物品一个十分重要的过程,再看本片之前首先要看前面的Entry3


事实上作为嵌套,随机概率的算法也是嵌套的.
公式:对于n个嵌套loottable


    一个项目的真实权重[n]=(该项目权重+该权重增值*幸运值)
   random_chance[n] = 随机点数【随机点数】或者(基础点数+抢夺附魔等级*等级乘数)【抢夺判定】
   一个loottable的概率=(一个项目真实权重[n]/项目列表真实权重总和[n])* random_chance[n] * (1-set_count中选中0的概率[n])
*注解:set_count选中0的概率靠这样计算:例如min:0,max:10,那么一共可能有11种数量结果,那么选中0的概率就是1/11.

总的来说,概率的算法就是(loottable1中抽到loottable2的概率)*(loottable2中抽到loottable3的概率)*……*(loottablen-1中抽到loottablen的概率)

Loottable概率调整及平衡物品
如果一个物品破坏了地图的平衡性,我们可以通过调整概率来平衡物品.
比如以下三个Loottable嵌套关系:

代码:

  1. Loottable0
  2. {
  3.     "pools": [
  4.   {
  5.    "rolls": 1,
  6.    "entries": [
  7.     {
  8.   "type": "loot_table",
  9.   "name": "test:loottable1",
  10.   "weight": 1
  11.     },
  12.     {
  13.   "type": "empty",
  14.   "weight": 1
  15.     }
  16.    ]
  17.   }
  18.     ]
  19. }
  20. Loottable1
  21. {
  22.     "pools": [
  23.   {
  24.    "rolls": 1,
  25.    "entries": [
  26.     {
  27.   "type": "loot_table",
  28.   "name": "test:loottable2",
  29.   "weight": 1
  30.     },
  31.     {
  32.   "type": "empty",
  33.   "weight": 1
  34.     }
  35.    ]
  36.   }
  37.     ]
  38. }
  39. Loottable2
  40. {
  41.     "pools": [
  42.   {
  43.    "rolls": 1,
  44.    "entries": [
  45.     {
  46.   "type": "item",
  47.   "name": "minecraft:diamond",
  48.   "weight": 1
  49.     },
  50.     {
  51.   "type": "empty",
  52.   "weight": 1
  53.     }
  54.    ]
  55.   }
  56.     ]
  57. }

这里随机到钻石的概率是0.125,如果我想时概率降低到0.1,先要计算出所有非底级Loottable中随机到该Loottable的概率:
0.25
接着通过理想概率/这个值的到该物品理想权重比例:
0.1/0.25=0.4
接着计算出项目列表中其他项目权重总和:
empty总和为1
接着用其他项目权重总和/(1-理想权重比例)*理想权重比例得出最后权重:
1/(1-0.4)*0.4≈0.67


Loottable文件夹管理
当你建立一个复杂的loottable体系时,嵌套是不可或缺的.


而Loottable文件夹的管理,关系到了往复调用中是否能够逻辑清晰:

地心之路中使用的物品loottable,由于loottable只能支持二级文件,路径不能无限子文件夹,因此你可以把文件夹分细一点.(地心之路loottable嵌套级别为3)(目前支持无限子文件夹了)
例如在此处我将每一种类物品都归纳进入一个命名空间,这样再调用的时候结构分明.
(每一个子loottable的内容都只有一个权重为1的对应物品)


做完了这个步骤,再可以写更高一级的loottable


Loottable父子调用与完整Loottable包的制作
拿地心之路作为例子;
子:
一把剑

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": {
  5.     "min": 1,
  6.     "max": 1
  7.    },
  8.    "entries": [
  9.     {
  10.   "type": "item",
  11.   "name": "minecraft:iron_sword",
  12.   "weight": 1,
  13.   "functions": [
  14.    {
  15.     "function": "set_damage",
  16.     "damage": {
  17.   "min": 0.02,
  18.   "max": 0.02
  19.     }
  20.    },
  21.    {
  22.     "function": "set_nbt",
  23.     "tag": "{Unbreakable:1,AttributeModifiers:[{Operation:0,UUIDLeast:1,UUIDMost:1,Amount:5.5,AttributeName:generic.attackDamage,Name:Attack},{Operation:0,UUIDLeast:1,UUIDMost:1,Amount:0,AttributeName:generic.attackSpeed,Name:Speed}],ench:[{id:16,lvl:1}],HideFlags:63,display:{Name:\u00a77\u00a7l\u94c1\u5251,Lore:[\u00a77\u00a7n\u524d\u4eba\u7684\u9057\u7269]}}"
  24.    },
  25.    {
  26.     "function": "set_count",
  27.     "count": {
  28.   "min": 1,
  29.   "max": 1
  30.     }
  31.    }
  32.   ]
  33.     }
  34.    ]
  35.   }
  36.     ]
  37. }

必得物品.


父:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": {
  5.     "min": 1,
  6.     "max": 1
  7.    },
  8.    "entries": [
  9.     {
  10.   "type": "loot_table",
  11.   "name": "supply_food:1",
  12.   "weight": 1
  13.     }
  14.    ]
  15.   },
  16.   {
  17.    "rolls": {
  18.     "min": 1,
  19.     "max": 1
  20.    },
  21.    "entries": [
  22.     {
  23.   "type": "loot_table",
  24.   "name": "weapon_dagger:a",
  25.   "weight": 6
  26.     },
  27.     {
  28.   "type": "loot_table",
  29.   "name": "weapon_sword:a",
  30.   "weight": 3
  31.     },
  32.     {
  33.   "type": "loot_table",
  34.   "name": "weapon_gun:1",
  35.   "weight": 1
  36.     }
  37.    ]
  38.   },
  39.   {
  40.    "rolls": {
  41.     "min": 1,
  42.     "max": 1
  43.    },
  44.    "entries": [
  45.     {
  46.   "type": "loot_table",
  47.   "name": "supply_medicine:1",
  48.   "weight": 1
  49.     }
  50.    ]
  51.   }
  52.     ]
  53. }

随机中随机到的(weapon_sword:a)几率只有3/10


顶级:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": {
  5.     "min": 1,
  6.     "max": 1
  7.    },
  8.    "entries": [
  9.     {
  10.   "type": "loot_table",
  11.   "name": "supply:a",
  12.   "weight": 5
  13.     },
  14.     {
  15.   "type": "loot_table",
  16.   "name": "weapon:a",
  17.   "weight": 4
  18.     },
  19.     {
  20.   "type": "loot_table",
  21.   "name": "ragbag:a",
  22.   "weight": 2
  23.     }
  24.    ]
  25.   }
  26.     ]
  27. }

概率(weapon:a)是4/11


那么随机到该剑的概率只有:3/10*4/11=6/55


  • 完整包的制作
结合前面文件夹管理,嵌套n级(顶级)→嵌套n-1级→……→嵌套子级(底级)


如果需要平衡物品,结合前面的概率计算出所有物品的实际概率,接着改变顶级中的概率(如果改变底级的概率将会造成对于其他调用中波动很大)


关于Seed
如果你不想每一次更新Loottable都是随机的物品,那么你可以用一个Seed来规定调用loottable时的随机种子,让Loottable按相同种子随机.
也就是说每次随机的物品都是确定且相同的.


例如:

代码:

  1. setblock ~ ~1 ~ minecraft:chest 0 0 {LootTable:"minecraft:chests/jungle_temple",LootTableSeed:100L}

那么每次从jungle_temple中抽取物品不是随机的,而是依靠随机种子100L的物品.


下面分析以下两个标签:
LootTableSeed:长整型,是对于容器来说Loottable的随机种子.
DeathLootTableSeed:长整型,是对于实体来说Loottable的随机种子.

如果后面填0L,那么相当于没有种子,依旧是完全随机.


Seed的用途就是让随机产生的物品成为一个种子产生的特定物品,而不是每次更新了容器、实体都完全随机.


关于幸运值
幸运值由下面几个项目来呈现:
luck药水效果、unluck药水效果、物品属性generic.luck、海之眷属附魔.

最终幸运值公式:
Operation:2(属性的效果为提升百分比):(luck药水效果-unluck药水效果)*generic.luck+海之眷属附魔;
Operation:0(属性的效果为提升值):luck药水效果-unluck药水效果+generic.luck+海之眷属附魔;


*注:海之眷属附魔只适用于钓鱼机制.


结合指令1 实体抽奖机
顾名思义,通过Loottable的实体随机掉落来制作抽奖机.
尽管要调用外置资源,但是待抽取的物品十分丰富,只需要拟写一份Loottable即可.


Roll:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "diamond",
  9.   "weight": 5
  10.     },
  11.     {
  12.   "type": "item",
  13.   "name": "gold_ingot",
  14.   "weight": 10
  15.     },
  16.     {
  17.   "type": "item",
  18.   "name": "iron_ingot",
  19.   "weight": 25
  20.     },
  21.     {
  22.   "type": "item",
  23.   "name": "coal",
  24.   "weight": 60
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }

接着

代码:

  1. /summon Zombie ~ ~ ~ {DeathLootTable:"Roll:Roll",CustomName:"Roll",Silent:1b}

按下一次按钮就

代码:

  1. /kill @e[type=Zombie,name=Roll]

即可


注意不要关闭实体掉落


结合指令2 随机器
刷怪笼拟写很麻烦,@r随机器需要进行实体列阵穷举,由于Loottable也是随机性,可以结合指令制作一个随机器
Roll:

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "diamond",
  9.   "weight": 5
  10.     },
  11.     {
  12.   "type": "item",
  13.   "name": "gold_ingot",
  14.   "weight": 10
  15.     },
  16.     {
  17.   "type": "item",
  18.   "name": "iron_ingot",
  19.   "weight": 25
  20.     },
  21.     {
  22.   "type": "item",
  23.   "name": "coal",
  24.   "weight": 60
  25.     }
  26.    ]
  27.   }
  28.     ]
  29. }

这个随机器就有四个穷举对象,物品:钻石,金锭,铁锭,煤.
概率分别是5% 10% 25% 60%


利用实体抽奖机的方法,

代码:

  1. /summon Zombie ~ ~ ~ {DeathLootTable:"Roll:Roll",CustomName:"Roll",Silent:1b}

随机一次就

代码:

  1. /kill @e[type=Zombie,name=Roll]

接着检测掉落物


然后产生输出

代码:

  1. /testfor @e[type=Item] {Item:{id:"minecraft:coal"}}

代码:

  1. cond:/execute @p say 1


结合指令3 判定条件死亡
因为有DeathLootTable,在实体死亡后可以调用Loottable产生掉落物,结合Conditions我们可以进行复杂的死亡条件检测.

代码:

  1. {
  2.     "pools": [
  3.   {
  4.    "rolls": 1,
  5.    "entries": [
  6.     {
  7.   "type": "item",
  8.   "name": "minecraft:potato",
  9.   "weight": 1,
  10.   "functions": [
  11.    {
  12.     "function": "minecraft:set_nbt",
  13.     "tag": "{display:{Name:a,Lore:}}"
  14.    },
  15.    {
  16.     "function": "minecraft:furnace_smelt"
  17.    }
  18.   ],
  19.   "conditions": [
  20.    {
  21.     "condition": "minecraft:killed_by_player",
  22.     "inverse": false
  23.    },
  24.    {
  25.     "condition": "minecraft:entity_properties",
  26.     "entity": "this",
  27.     "properties": {
  28.   "minecraft:on_fire": true
  29.     }
  30.    }
  31.   ]
  32.     }
  33.    ]
  34.   }
  35.     ]
  36. }

这样,只需要检测一个名为a,附注为b的烤土豆就能知道这个实体在着火的情况下被玩家杀死:

代码:

  1. /scoreboard players tag @e[type=Item] add tag {Item:{id:"baked_potato",tag:{display:{Name:a,Lore:}}}}
  2. cond:操作
  3. /kill @e[tag=tag]




尤里の猫_
看脸?毕竟我脸好

堪堪堪
这....我什么都看不懂,这个是CB的么?

leavessoft
没看懂,被1.9新特性吓退了已经

无奈丶屮艸
只玩1.8以下的表示一脸懵逼

彪悍的新手
看起来不错
学习一下

chyx
目录有一行错位了 请修理

chyx


Loottable循环嵌套这一节我没有重复出无限调用 可能是因为我在1.10 moj不让循环引用了


普通调用也是有的时候没有物品 而不是总有物品

chyx
而且 我有一个疑问
set_attributes在1.9快照时期被加入了
但您举得


“Loottable父子调用与完整Loottable包的制作” 中的地心之路的例子却在nbt里指定了属性 这是否说明nbt优先于这个function?还是并列的?附魔属性和setnbt又有什么关系?

ruhuasiyu
function1 的第一段代码挂了

fengjingMC
现在1.10.2里可以很多层嵌套了,反正我试了一下八层没问题……希望lz改一下
  1. {LootTable:start:one/two/three/four/five/six/seven/eight/end}
复制代码

jimmy1234
我竟然看懂了!
太不可思议了!
好像总索引的名字和这个不一样
看脸讲玄 or 看脸看玄?

_Rainbow_
原来是自己创么。。一脸黑线

ShiGuangChong
(⊙v⊙)嗯......很简单的表示

BlackCB.
制造看脸看玄的世界??(一脸懵逼)

然而连计分板都不太懂的我表示看不懂。。。

MC北辰
感谢,MCBBS有你更精彩~

Hytrophoton
箱子无限嵌套是不是少了一个BlockEntityTag

白色的小熊
你这是写的1.12的吗?1.13的呢

白色的小熊
怎么加多个函数?

Skyngard
脸黑啊,awa qwq


wangduo110
一脸懵逼的进来 一脸懵逼的出去

第一页 上一页 下一页 最后一页