跳到主要内容

创建 Boss 阶段

Boss 阶段允许自定义 Boss 在遭遇战中更换配置。

Boss 阶段如何运作?​

可以使用以下配置格式为 EliteMobs 中的任何自定义 Boss 添加 Boss 阶段:

phases:
- phase_2_boss.yml:0.X
- phase_3_boss.yml:0.Y

注意:你最初生成的 Boss(也就是包含列出所有其他阶段的 phases: 条目的那个)是第 1 阶段的 Boss。第 1 阶段的 Boss 文件不应在它自己的 phases: 条目中列出自身。

每个条目的格式为 filename:healthFraction。比例必须大于或等于 0 且小于 1,例如 0.60 或 0.30,并且引用的 Boss 文件必须已加载并启用。EliteMobs 每次创建该 Boss 时都会检查此列表:无效条目会阻止该 Boss 生成,控制台消息会指出是哪一个条目。

每个阶段引用另一个 Boss 文件,因此可以更改技能、伤害和生命值倍率、实体类型、伪装以及装备。遭遇战状态和下文列出的区域设置仍然共享。

EliteMobs 会保留遭遇战状态,并将 Boss 的实体替换为下一阶段。当一次伤害事件将生命值降至下一阶段阈值或更低时,该事件会被取消,新阶段以配置的生命值比例开始。多余伤害不会带入新阶段。之后 Boss 会获得 20 tick 的战斗宽限期。

如果目标区块暂时还不能处理实体 tick,EliteMobs 会加载该区块,并在替换实体前最多等待 100 tick(5 秒)。等待期间,对 Boss 造成的伤害都会被取消。如果目标所在的世界未加载,或区块未能及时就绪,转换就会被拒绝:Boss 保持当前阶段,控制台会记录一条警告。

示例​

以这个示例阶段 Boss 为例:

文件:phase_1_boss.yml

isEnabled: true
level: 50
healthMultiplier: 10
entityType: STRAY
powers:
- attack_gravity.lua
phases:
- phase_2_boss.yml:0.60
- phase_3_boss.yml:0.30

文件:phase_2_boss.yml

isEnabled: true
level: 50
healthMultiplier: 10
entityType: SKELETON
powers:
- attack_gravity.lua
- arrow_fireworks.lua

文件:phase_3_boss.yml

isEnabled: true
level: 50
healthMultiplier: 10
entityType: WITHER_SKELETON
powers:
- arrow_rain.lua

这就构成了一个有效的阶段 Boss。如果你生成 phase_1_boss.yml,它会生成一个带有上面所列属性的流浪者(Stray)。在被打到生命值 60% 时,它会立即在同一位置被替换成 phase_2_boss.yml 中所设定的自定义 Boss,因为配置文件中写明了 - phase_2_boss.yml:0.60(phase_2_boss.yml 是那个自定义 Boss 的文件名,0.60 即 60% 生命值)。请注意,第 2 阶段的 Boss 会以 60% 的生命值生成,因为那正是切换到该阶段的时刻。 该 Boss 将拥有 phase_2_boss.yml 文件中所列的技能。一旦第 2 阶段的 Boss 被打到生命值 30%,它就会生成为第 3 阶段所设定的 Boss。请注意,第 3 阶段的技能与之前的技能毫不相关——你可以在各阶段之间完全更换技能,就像几乎所有其他属性一样。

进阶​

继承的机制​

以下是一些在各阶段之间不会改变的内容列表:

  • 链条中的第一个阶段 Boss 决定了 Boss 将经历哪些阶段,意味着你不应为该阶段中的其他 Boss 添加 phases 条目。

  • 威胁表 / 伤害表保持不变,意味着战利品分配和高级仇恨系统不受阶段切换的影响

  • 阶段切换使用下一阶段配置的生命值比例。如果第 2 阶段在 50% 时开始,它会获得自身最大生命值的 50%,即使触发转换的攻击原本会让上一阶段降到该阈值以下。各阶段可以有不同的最大生命值。

全都卡在生命值上限的各阶段是完全一样的

Boss 生命值会被钳制在服务器的 settings.attribute.maxHealth.max(默认为 2048)。如果多个阶段配置的 level 和 healthMultiplier 高到足以触及该上限,它们最终都会恰好是 2048 点生命值,你原本设想的各阶段生命值差异也就随之消失。本页的示例(level: 50、healthMultiplier: 10)正处在这个区间 —— 每个倍率在多少级时会触顶,请参见 healthMultiplier。

  • 符合条件的非实例阶段 Boss 会在脱战回血系统调用 fullHeal() 时返回第 1 阶段。这需要启用 regenerateCustomBossHealthOnCombatEnd;该事件路径不包含幻翼。实例 Boss 会跳过 fullHeal()。普通治疗达到满血本身不会触发阶段重置。

  • 区域阶段 Boss 保留第 1 阶段建立的牵引半径和重生冷却,并在冷却后以第 1 阶段重生。阶段转换使用静默生成,不会重新启动逃脱计时器;请在第 1 阶段配置整场遭遇战的 timeout。

  • 第 1 阶段也决定整条阶段链的 normalizedCombat。设置 level: -1 的阶段会保留已经确定的遭遇战等级,包括实例所选等级;新阶段明确指定的等级会替换它。

阶段专属生成位置​

默认情况下,Boss 在阶段之间转换时会停留在其当前位置。不过,你可以使用 phaseSpawnLocation 设置让 Boss 在进入某个阶段时传送到特定位置:

文件:phase_2_boss.yml

isEnabled: true
level: 50
healthMultiplier: 10
entityType: SKELETON
powers:
- attack_gravity.lua
- arrow_fireworks.lua
phaseSpawnLocation: world_name,100,64,100,0,0

你也可以在保持 Boss 处于同一世界的情况下将其传送:

phaseSpawnLocation: same_as_boss,100,64,100,0,0

这对于打造戏剧性的阶段转换很有用,让 Boss 传送到不同的竞技场或位置。

警告​

以下是一些运作方式可能初看违反直觉的机制列表:

  • EliteMobs 的普通伤害无法一击跳过有效的下一阶段:达到阈值的攻击会被取消,并前进一个阶段。战利品取自 Boss 真正死亡时生效的配置。请配置最终阶段的奖励。当转换被拒绝时(例如 phaseSpawnLocation 指定的世界未加载),达到阈值的攻击仍会被取消,因此在问题修复之前,普通伤害无法将 Boss 打到该阈值以下。

  • 每个阶段都会运行生成流程,包括适用的 onSpawnCommands。阶段转换和满血重置使用静默生成,不发送普通生成公告。区域 Boss 在冷却后重生时可以再次公告。阶段转换不是死亡,不会执行死亡命令。

  • 区域阶段 Boss 会先应用离开阶段的 ON_REMOVE 过渡方块,再进入新阶段。新阶段随后应用生成方块。真正死亡或使用 kill 命令时,会应用最终阶段的移除方块。普通区块卸载和满血重置不算作这种清理所需的击败。

  • 阶段转换会移除上一阶段追踪的坐骑,然后按新阶段配置创建坐骑。满血重置也会移除当前坐骑,并使用第 1 阶段的坐骑配置。

  • 每个阶段都会重新加载技能,因此 custom_summon 技能的 ONCE 增援状态会在切换阶段或重置到第 1 阶段时重置。它并不是整场遭遇战仅限一次。

技巧与窍门​

  • 你可以利用装备和实体类型可以在整个战斗过程中改变这一点,让 Boss 在战斗中显得越来越(或越来越不)危险

  • 虽然可行,但除非有特定的设计目标,否则阶段 Boss 的技能最好不要在各阶段之间变化得太过剧烈,因为玩家更可能享受一种在整场战斗中感觉自然的进程。

  • 你可以使用 onSpawn 命令在阶段之间运行命令

  • 为需要更换音乐的阶段设置 song。不同的值会替换曲目,相同的值会继续播放。后续阶段省略 song 不会停止上一首曲目。

  • 阶段可用于让 Boss 在近战与远程模式之间相互切换

  • 阶段 Boss 的设计初衷是成为拥有大量 HP 的强力 Boss。它们通常最适合作为地下城的最终 Boss 遭遇战,或作为大型世界 Boss。

  • 增援可能在阶段间存活。上一阶段的 cullReinforcements 控制清理;重置到第 1 阶段也会请求清理增援。

  • Boss 可以拥有任意数量的阶段,但阶段越多,它们就需要越多的生命值才能让每个阶段都有意义。

API 集成​

面向插件开发者:当 Boss 在各阶段之间转换时,EliteMobs 会触发 ElitePhaseSwitchEvent 事件。这个事件可用于在阶段转换期间创建自定义行为或效果:

重置到第 1 阶段也会触发该事件。它在新阶段的实体生成之后触发,此时生命值比例和 20 tick 的战斗宽限期均已应用。需要等待目标区块的转换,只有在实体出现时才会触发该事件。

@EventHandler
public void onPhaseSwitch(ElitePhaseSwitchEvent event) {
CustomBossEntity boss = event.getCustomBossEntity();
PhaseBossEntity phaseBoss = event.getPhaseBossEntity();
// Your custom logic here
}