【命令/数据包】如何制作原版RPG生物/如何间接绕过原版血量上限

让你成为一名RPG数据包作者!

Featured image

引言

RPG类游戏一直是Minecraft地图以及服务器的香饽饽。

但是,众所周知的是,原版RPG游戏难以制作复杂的敌对生物。原版生物的行为不能说智能,只能说是制杖。

(如果你比较有时间,也不是不能强行写一个自定义的生物行为出来,但是代价嘛……)

更甚至,RPG游戏一向是数字越大体验越好,但原版Minecraft将生物最大生命值限制在了1024……

诚然,你也许会说,直接下载一个Epic Mobs插件不就好了吗

但是插件存在版本局限性,新版本出来的时候插件日常跟不上;再者就是例如Realms等平台并不支持插件的使用

因此,本文特介绍一下常用的一些在原版中制作突破原版属性限制的RPG生物的方式,以及一部分以较低代价制作更智能的生物行为的思路

第一部分:原版修修补补能达到的最大生命值?

首先要明确一点:原版生物的生命值是由nbt中的Attribute控制的。1.15之前的版本为Attribute.maxHealth, 1.15后统一改成了Attribute.max_health

该属性键值最大为1024点

但同时,你还可以为生物附加伤害吸收效果。满级伤害吸收效果(minecraft:absorption)可以为生物提供1024点金血。这样可以为生物达到总计2048点生命值

显然,2048对于“数字越大,玩的越爽”来说,也只能算是杯水车薪。这时就要请出另一个状态效果——抗性提升(minecraft:resisitance)了。

4级抗性提升可以为生物提升80%伤害减免,也就是让生物的实际有效生命值提升为原本的5倍。因此理论上,原版中可以为生物获取的最大有效生命值为10240点。

这有效缓解了一部分对数值的渴望。然而,这显然是不够的。因此,接下来的方案,请您接着往下看

第二部分:引入假血(记分板)的概念

严格意义上讲,生命值只是一种简单的统计方式。生命值>0意味着该生物可以继续行动,生命值<0判定该生物死亡,掉落物品且清除该实体

聪明的你看到上面这句话可能已经想到解决问题的思路了:我要做的只是判定生物是否仍有大于0的某数据即可。那么,只需要比较表示生命值的记分板数据是否大于0即可

很可惜,原版Minecraft中的health记分板为只读,因此你仍无法直接读取超过2048点的生命值。不过,为什么不自己做一个dummy记分板,自己写自己的血量呢?

1.12后引入的function功能彻底改变了原版模组的逻辑与制作方式。同时期引入的advancement也为我们提供了一种快捷而经济的检测手段。

检测玩家伤害某实体->检测该实体的生命值减少量->将该实体生命值减少量存在记分板1中->用代表当前生命值的记分板2减去记分板1的分数->得出生物受到伤害后的当前生命值,如果小于0则判定该生物死亡;如果大于0则记录当前生命值并将该生物的实际minecraft恢复满

以1.14+版本指令格式为例,你只需要这样写 首先是一个简单的advancement

{
  "criteria": {
    "requirement": {
      "trigger": "minecraft:player_hurt_entity",
      "conditions": {
        "entity": {
          "nbt": "{Tags:["hp_target"]}"
        }
      }
    }
  },
  "rewards": {
    "function": "rpg:hp_remove"
  }
}

检测玩家对taghp_target的实体造成伤害,并执行rpg文件夹下的hp_remove函数 然后

scoreboard objectives add CurrentHealth dummy
scoreboard objectives add HealthLosen dummy

制作三个涉及生命的记分板 然后

execute as @e[limit=1,sort=nearest,tag=hp_target] store result score @s HealthLosen run data get entity @s Health
execute as @e[limit=1,sort=nearest,tag=hp_target] store result score @s HealthLosen run data get entity @s Health
execute as @e[limit=1,sort=nearest,tag=hp_target] run scoreboard players remove @s HealthLosen 10240
execute as @e[limit=1,sort=nearest,tag=hp_target] run scoreboard players operation @s CurrentHealth += @s HealthLosen

至此,你就完成了一次简单的生命值计算。最后别忘了给怪回血

使用以上一套组合拳,我们便得到了一份”假血”。这“假血”所允许的最大值为记分板所允许的最大值,远大于minecraft中能达到的最大生命值。

至此,你扬眉吐气,制作许久(也可能不久)的RPG服终于可以开服了。服务器一直运营的很好,你也打着你的小算盘,时不时在游戏里添加一些属性更好,当然也卖的更贵的装备。直到有一天,你为服务器商店中添加了一份新装备,不要88,不要168,只要998。

你开心的看着后台的进账,笑得合不拢嘴,决定上线看看。但当你进入游戏的时候,却不经意间在左下角的聊天框看到了这样的消息:

[16:38:51] <游戏寄巧国服第一> 世界Boss车,有钱你就来
[16:39:12] <游戏寄巧国服第一> 世界Boss车,有钱你就来,还有最后一个位子
[16:39:22] <我是qlk的狗> 大佬能带一个吗,打完boss拿货付款
[16:39:30] <游戏寄巧国服第一> 概不赊账的嗷
[16:40:00] <我是qlk的狗> 呜呜呜求求了大佬你最厉害了先带一次行嘛
[16:40:13] <游戏寄巧国服第一> 行吧,待会打完BOSS记得在公屏发喇叭,让那个谁谁看看,谁才是老大
[系统消息] 世界boss 被 <游戏寄巧国服第一> 击杀

你惊呆了,有6000万生命值的boss居然被人在一分钟之内薄纱了。你赶忙点开该玩家的面板想要一探究竟。然而,令你惊讶的是,该玩家手里除了一把武器以外,什么都没有带。

你百思不得其解,难道是自己的指令写出什么问题了吗?可是,这个boss明明有高达6000万的生命值,而这把武器仅仅有2万点伤害啊

问题就出在这里

第三部分:以大一点的代价,收获大很多的价值

显然,在你被“6000万”和“2万”这两个简单的数字蒙蔽了双眼的时候,忘记了前文中提到的最重要的一点——MC原版允许的最大生命值,算上各种状态效果缝缝补补,也只有10240点。

尽管你可以完事后给怪尽情回血,把血条上限顶破都没事,但是你别忘了,如果一刀把怪砍死,检测的时候可就没有这个怪了,更没有后面的事情了

你傻了,你确实忘了有这回事了。现在摆在你面前的是,你不能把玩家价值998的新武器没收掉,只能想办法改进一下你的boss了

已知,抗性提升5可以让怪物达到伪无敌的效果,肯定能脸接2万伤害了。那么,有没有办法让抗性提升5的怪物仍然被统计实际上收到的具体伤害数值呢?

哎,还真有

记分板除了healthdummy两种类型,还支持检测minecraft中各种不同的统计数据

其中包括了“伤害吸收量”和“伤害免疫量”这两组数据

在1.14+版本中,其格式为minecraft.custom:minecraft.damage_dealt_resisted

通过这种方法,你可以制作出一个名义上可以打败,实际上“无敌”的Boss

到这里,你终于扬眉吐气,可以继续高高兴兴的卖你的998了

虽然多一个记分过程,对性能占用有略微的提升;但是为了“数字越大,打得越爽”,

这一切或许也是值得的?