帕尔等级缩放 - 野外帕尔以与你相同的等级生成

帕尔等级缩放 - 野外帕尔以与你相同的等级生成

Wild Pals改为根据附近玩家的等级刷新,而非区域的固定等级,因此早期游戏后,地图的一半不再只是风景。区域仍决定出现哪些Pals;模组决定其等级。默认仅向上调整。服务器端——客户端无需安装任何内容。

野生帕鲁(Pal)的等级与附近玩家同步,而非固定于区域等级

在原生版本中,每只野生帕鲁的等级由所在区域决定。游戏前期过后,这会让半个地图形同虚设:你穿行于满是 5 级生物的区域,它们既不提供经验,也无法带来战斗体验,更不值得浪费一个帕鲁球。

本模组将帕鲁的等级与附近的玩家绑定。区域仍然决定哪些帕鲁会刷新,而模组则决定它们以什么等级出现。

服务端模组,客户端无需安装任何文件

纯 Lua 编写,由专用服务器上的 UE4SS 加载。PC、Xbox 和 PlayStation 玩家无需修改任何文件,即可获得一致的体验。

已在原生 Linux 专用服务器上经过生产环境测试,使用的是我们的 GLIBC 2.28 UE4SS 构建版——该页面是让此模组能在 Linux 上运行的关键组件,因此被列为本模组的必需依赖。在 Windows 专用服务器上,则使用官方 UE4SS 即可。

测试环境:帕鲁世界 v1.0.2.101103,UE4SS 3.0.1,原生 Linux(BisectHosting)。


工作原理

当服务器即将决定一只野生帕鲁的刷新等级时,模组会拦截该过程,并根据附近玩家的等级提供一个新等级。

等级 = 参考玩家等级 +/- 随机浮动

在默认设置下,一名 80 级玩家附近生成的帕鲁等级会在 78 到 82 之间浮动。

模组只会向上调整,绝不会向下调整(scalingDirection = "up_only")。例如,在终局区域原本就会以 90 级刷新的帕鲁,仍会保持 90 级——模组不会将一个区域的等级拉低到玩家的水平。

安装方法

ue4ss/Mods/PalLevelScaling/
|- enabled.txt          <- 空文件,但必需
|- Scripts/
   |- main.lua
   |- config.lua

在服务器停止状态下复制文件。启动后,在 UE4SS.log 中确认以下信息:

Loaded; enabled=true, ..., levelScaling=true, ...

然后在游戏中走动,即可看到类似日志:

Scaled Pal 16 -> 79 (player-relative/nearest_to_spawn_location/up_only, nearby players=1)

配置选项

所有配置均位于 Scripts/config.lua 文件中。

modEnabled                     true      开启模组
scaleSpawnLevels               true      主要功能开关
levelsBelowSelectedPlayer        2      可低于参考玩家的最大等级数
levelsAboveSelectedPlayer        2      可高于参考玩家的最大等级数
scalingDirection          "up_only"      up_only / down_only / both
playerLevelSelectionMode    "lowest"     选择哪位玩家作为参考
protectLowLevelAreas           true      详见下文
maxWildPalLevel                100      绝对等级上限
enforceMaxWildPalLevelGlobally true      即使不缩放也应用上限
playerDetectionRangeBuffer    2000      寻找玩家时的额外检测范围
strictPlayerLevelSource        true      详见下文 - 重要
configAutoReloadEnabled        true      无需重启即可重载配置文件
configAutoReloadIntervalSeconds 300

playerLevelSelectionMode(参考玩家选择模式)

  • lowest - 选择附近玩家中等级最低者。此为默认设置
  • highest - 选择附近玩家中等级最高者
  • nearest_to_spawn_location - 选择距离帕鲁刷新点最近的玩家

lowest 作为默认设置的原因在于,在共享服务器上,此设置永远不会让任何玩家陷入困境:一位老玩家经过时,不会在 30 级新手朋友周围留下 80 级的帕鲁。如果你的玩家大多分开活动,可以切换到 nearest_to_spawn_location,这样地图的每个角落都会跟随该处的玩家等级。

protectLowLevelAreas(保护低等级区域)

开启后,如果缩放会导致该区域的等级超出在线最低等级玩家的能力范围,模组将拒绝进行缩放。它只在此种情况下阻止缩放——并非全局上限,也不会在附近玩家等级相近时进行干预。

strictPlayerLevelSource(严格玩家等级读取)

开启后,如果模组无法确定地读取玩家等级,将放弃缩放。关闭后,则会接受最后读取到的数值。

建议保持开启。读取失败恰好发生在玩家刚连接、角色仍在初始化时——此时读取到的值通常是 1。如果接受这个值,就意味着每次连接后的最初几秒,地图上会永久性地充满 1 级帕鲁(因为它们不会自己重新刷新)。

宁可减少缩放的帕鲁,也不要错误地缩放帕鲁。

常用调整

  • 更大的等级浮动 - 设置 levelsBelowSelectedPlayer = 5levelsAboveSelectedPlayer = 5
  • 同时下调终局区域等级 - 设置 scalingDirection = "both"
  • 限制最高等级 - 设置 maxWildPalLevel = 60
  • 仅观察,不改变 - 设置 scaleSpawnLevels = false(仍会写入 CSV 日志)

决策日志

writeDecisionCsv 设为 true 后,模组会在每次会话中写入一个 CSV 文件,记录每一次决策——原始等级、新等级、所参考的玩家、距离和原因。这对于理解为什么某只特定帕鲁没有被缩放很有帮助。

Scaled Pal 16 -> 79 (player-relative/nearest_to_spawn_location/up_only, nearby players=1)
Decision UNCHANGED/players_inside_radius_but_no_valid_levels:...|strict_skip

第二行是 strictPlayerLevelSource 在发挥作用:附近有玩家,但无法读取其等级,因此该帕鲁保持原样。

兼容性良好的模组

PalLootScaling 使用玩家等级来决定战利品倍率。由于本模组会将野生帕鲁的等级与玩家等级对齐,两者可以很好地配合:战利品加成最终会与玩家实际击杀的帕鲁等级相匹配。

PalCaptureBosses 不受影响——Boss 拥有独立的等级系统,不会经过本模组的处理。

已知限制

仅影响尚未刷新的帕鲁。 已经在世界中存在的帕鲁会保持其原有等级。修改配置后,请前往另一个区域或重启服务器以观察效果。

不影响 Boss、高塔阿尔法或任务帕鲁。 这些帕鲁的等级在其他地方设定。

玩家的等级是在帕鲁刷新时读取的。 如果附近没有玩家,帕鲁将以该区域原有的等级刷新。

如果你正在为 Linux 服务器开发模组,请注意

并非所有 UE4SS 的调度机制都能在 Linux 构建版上正常工作:

RegisterHook                    正常工作
ExecuteInGameThread             正常工作
ExecuteInGameThreadWithDelay    正常工作,且准时触发
ExecuteWithDelay                永远不会触发
LoopAsync                       永远不会触发

缩放功能本身使用 RegisterHook,始终运行正常。配置自动重载需要一个定时器,早期版本使用了 LoopAsync:日志中显示“每 300 秒检查一次 config.lua”,但实际上从未检查过。因此配置修改需要重启才能生效,且没有任何提示。

如果某个功能无法正常工作而日志却显示正常,请先怀疑调度器,而不是你自己的逻辑。详细说明和解决方法请参见 UE4SS Linux 构建版页面

源代码

完整源代码、技术文档和问题追踪: github.com/prado1506/palworld-PalLevelScaling

本模组是经过原生 Linux 专用服务器验证的系列服务端帕鲁世界模组之一。它们共同依赖的加载器在此处