波 次 、 胜利 与 关 卡 推进
推进波次、结束战斗与继续挑战的不同规则。
约 8 分钟
波次时钟判断是否推进计划;胜利判断所有已注册完成条件是否都通过;失败模块判断符合条件的僵尸是否越过边界。这些问题检查不同状态,因此同一个幸存者可以与下一波的生命值阈值无关,却仍阻止胜利。
动作 完成 之后 记录 生命 值
波次开始时,Wave 先调用所有动作,再记录 m_current。查询按 m_spawned 与一个虚拟状态谓词筛选实体。基础生命值实现在实体标记掩码 0x2 被设置时,将本体加头盔 HP 转换为整数,否则返回零。
令 为这个初始当前波次报告总量, 为下文详述的有符号 32 位转换。对于抽取比例 ,保存的整数阈值为
这里使用构造器基线。之后的检查重新查询剩余生命值 ,点数成本与玩家累计伤害都不能替代该查询。11动作完成后的生命值快照波次开始时先调用所有动作回调,再查询符合条件的当前波次生命值并保存到 m_currentWaveTotalHealth。查询筛选生成波次标记与排除状态,并取得虚拟生命值。之后的检查将重新查询的生命值与保存的整数阈值比较。位置拒绝早于初始查询;查询之后的死亡可以降低剩余生命值,而不重写快照。0x101ce76d80x102082abc0x101ce7ce00x1019b09c00x10199dfc80x101988e70
例如,8,000 合格 HP 加上一个在放置时被拒绝的 2,000 HP 新实体,会得到 ; 时得到 。系统不会先记录 10,000 HP,再把拒绝记为 2,000 伤害。如果已计入的僵尸之后消失,即使没有植物攻击,后续剩余生命值总量仍可下降。
基础当前波次状态筛选
基础虚拟谓词排除以下注册状态。子类可以覆盖该谓词。此筛选与下方胜利扫描不同。
很大 的 HP 报告 值 会 达到 整数 上限
可执行程序采用 ARM64,但这条路径混合使用 float32 运算与有符号 32 位整数报告值。基础读取函数将本体与头盔 HP 相加,再把和转换为整数。波次查询将每个报告的贡献重新转换为 float32,按顺序累加,最后再次把累加值转换为整数。
对于正 HP, 在范围内向零截断,超出范围时饱和到 。转换不会将很大的正报告值回绕成负数。存储的生命值字段与这个有上限的报告值相互独立。22Float32 累加与有符号 int32 报告基础读取函数使用 FCVTZS W0 转换 float32 的本体与头盔之和。波次查询将每个有符号贡献转换为 float32,加入 float32 累加器,再用 FCVTZS W0 转换最终和。非陷阱 FP 行为下,超范围的正数转换饱和到 2147483647。阈值使用截顶后的初始报告值。ARM64 算术检查覆盖转换边界、顺序舍入,以及 0.7、0.8、0.85 比例。0x10199dfc80x102082abc0x101ce76d80x101ce7298
初始查询一旦饱和,保存的基线就不再随未截顶的累加值继续增长。以下阈值包含原生 float32 舍入:
对于构造的初始累加值 10,000,000,000 HP,若 ,剩余报告值必须降到约 1,717,986,944。这相当于初始量减少约 82.82%,而非 20%。只要剩余报告值也仍然饱和,它就依然高于更小的阈值。普通计时器可以更早推进波次;饱和不会停用该计时器。
进度计算也使用报告的当前/初始生命值比值。两次报告都饱和时,比值保持为 1,波内进度中由生命值决定的部分保持为零。如果单个基础读取函数达到同一上限,被截顶的也只是其报告贡献;此查询不会减少它保存的本体或头盔 HP。
舍入在饱和之前也可能产生影响。在构造的 79 个贡献序列中,每个贡献为 27,000,000,经过检查的 float32 累加结果为 2,133,002,496。改为 80 个这样的贡献后,累加值为 2,160,002,560,返回的总量则为 2,147,483,647。构建视图现在对其合格普通动作小计执行这些报告转换。
无尽实战参考给出的等级 10 生命值倍率为 100,000,使基础 HP 270 变为 27,000,000。一波的 HP 取决于最终生成的实体及其强度。最后一个计划波次之后没有额外的普通批次。
截止 时间 可以 提前
令 为上一波时间, 为选定间隔,初始 。普通间隔为 20 加上在 0–5 游戏秒中抽取的浮点值;下一波为大波时,则为 35 秒。
剩余生命值检查通过时,普通路径按下式更新截止时间:
在满足普通状态/模式条件的前提下,推进检查随后要求
因此,提前达到生命值阈值会使截止时间到期,却不会消除这条路径的四秒最小间隔。即使 ,也仍经过时间条件。
如果下一波是大波,普通路径先进入提示状态,并在已有截止时间上加上 Huge。构造器延迟为 5 秒。它不是从进入提示的时刻重新启动独立的五秒计时器。当 ,并在 达到生命值阈值时,普通路径的第一个推进条件在 4 时成立,但偏移后的截止时间是 。没有提前生命值触发时,35 秒的截止时间变为 40。33计时推进与大波延迟普通计时状态的更新同时检查下次截止时间、距上一波的最小间隔,以及模式条件。生命值路径可以提前截止时间。大波提示状态在已有截止时间上加上 HugeWaveDelay。构造器时间值属于基线;WaveManager 属性还会尝试查询 DefaultWaveManagerProperties。0x101ce73800x101ce7ce00x101ce6fe0
启动有自己的倒计时:构造器值为普通模式 12 秒、传送带模式 5 秒。关卡/特权辅助函数可以修改普通启动值。这些是游戏时钟数值,与之后的波次间隔和僵尸移动速度分别处理。
自动 下 一波 使用 直接 请求
HasSkip 在请求的按钮可见性从假变为真时响应。普通计时状态在下列条件下请求显示:
因此,由生命值触发的较早 可以让按钮更早可用。若偏好设置与边界条件允许,Board 就发出与手动下一波相同的请求。普通请求直接调用推进函数,不重新执行普通截止时间、生命值或四秒检查。
对于当前玩家视角波号 、常规旗帜间隔 ,在已经开始一波之后,自动边界保护条件为
处理器还会在第一波之前抑制请求。这个边界表达式不独立检查最终波标记。第 81 关有 、:当前第 4 波受到保护;较短分组的最终第 13 波之前,当前第 12 波不受该表达式保护。
关闭选项后,普通推进仍然有效;开启选项,则增加这些手动式请求。由于触发点是可见性转换,在请求可见性持续为真时修改偏好设置,本身并不是又一次转换事件。44自动发出的手动式请求下一波可见性从假变为真的事件检查 HasSkipNextWave 与边界条件,再调用手动请求处理器。普通 WaveManager 分支直接调用推进函数。普通可见性条件使用 nextWaveTime 减去生成间隔的一半。自动保护条件使用常规 FlagWaveInterval;此处没有独立检查最终波标记。0x101581d5c0x101ce70940x101ce6e8c
在 提示 期间 点 击 , 会 留下 不同 的 状态
生成前的大波提示可能出现在常规旗帜波或最终波之前。普通计时更新在进入提示状态 2 之前已经请求显示下一波按钮,进入该状态并不会隐藏按钮。成功点击会到达直接推进处理器,它只拒绝已结束的状态 8。它立即开始提示所指的波次,并隐藏按钮。
这个提示与最终波开始时的消息不同。后者在最终波实际开始时发出,此时推进流程已经请求隐藏按钮。因此,仅仅看到一条提示,并不能确定按钮是否仍然可用。
差异来自手动路径缺少一次重置。提示到期时,流程先推进波次,再恢复普通计时。手动请求则直接调用推进,省略了该重置。开始新一波仍会替换上一波时刻与截止时间,因此原来的提示截止时间不再控制它。55手动推进省略提示状态重置普通按钮释放到达的请求只拒绝已结束的状态 8,随后直接推进。状态 2 的到期路径还会调用重置辅助函数,而手动路径省略此步。波次开始时写入新的截止时间,却不重置状态 2。该状态更新动作与进度,但省略普通 HP 提前触发与按钮可见性逻辑。最终波开始消息另行发出。受控的原始指令检查覆盖手动与计时的旗帜/最终波转换;外部服务与事件监听器使用桩处理。0x101fde6b40x101581c900x101ce6e8c0x101ce60080x101ce75280x101583bf8
以受控示例说明:当前为第 4 波,提示截止时间为 35。在 31 点击,会开始第 5 波。输入下一段间隔 22.5 后,它的新截止时间为 53.5。即使新一波在 36 清空,状态 2 也不会执行通常的 HP 提前触发。在 53.5,第 6 波开始,恢复普通状态 1。若等待原来的提示到期,则在 35 开始第 5 波,并立即恢复状态 1。
对于最终波,保留状态 2 同样可以在必须清除的敌人都已清空后推迟完成。在新的截止时间,波次向量耗尽会写入结束状态 8,但提示状态的调用者随后又将其重置为状态 1。再经过一次普通更新,才会保持结束状态。没有额外的计划波次,且实体清空谓词也必须通过。这些检查没有为额外更新确立固定时长。
交互视图的提示选项卡使用可编辑时刻和选定的清空事件来比较这些路径。该比较关闭自动下一波偏好,以单独检查手动请求。偏好设置的常规边界保护不会拒绝玩家点击。
初始 接近 速度 是 另 一个 选项
HasStart 在创建时与类型的 Hasty、生成波次标记及模式条件一起检查。接受的请求施加一个在后续调整前将移动速度翻倍的状态。它在游戏坐标 时清除。
Hasty 默认为真。当前无尽与传送门目录明确将 cannon、swashbuckler、west_ 和 lostcity_ 设为假。传送门标记 也不能通过创建路径的波次标记条件。之后被击退,并不会由这条路径重新施加初始状态。66创建时的初始加速状态实体创建检查档案选项、HastyOnStart、波次标记及模式排除条件,再施加状态 7。状态追踪器在后续调整前将移动速度因子翻倍。僵尸更新在 X <= 792 时清除该状态。这条创建分支不会在击退后重新施加。目录中四个明确为假的类型标记保留在参考数据中。0x1015946a80x1019853a80x101999778
这影响符合条件的实体多快抵达草坪,以及波次如何重叠,不会重新抽取类型池、改变点数预算或加速全局游戏时钟。
完成 是 注册 谓 词 之间 的 逻辑 与
对于注册回调 ,
管理器拒绝空回调向量,并在第一个假结果处停止。这里两个必要检查是 Wave 已结束,以及 Zombies。前者在推进到已安装波次向量末尾时才结束;仅仅开始最终波,并不是这个转换。
Zombies 先扫描符合条件的 Board 僵尸指针,不将它们限制为当前波次。随后,它扫描相关网格物件集合,检查是否有物件的阻塞谓词返回真。因此,即使当前波次生命值已经达到阈值,较早幸存者、传送门子僵尸与传送门自身仍然可以产生影响。77完成是注册谓词之间的逻辑与模块管理器的汇总检查拒绝空谓词向量,并在第一个假结果处停止。WaveManager 注册结束状态检查;标准普通文件还注册 ZombiesDeadWinCon。后者扫描符合条件的僵尸指针,不限制为当前波次,应用明确的例外后,再检查网格物件集合 0x30 中阻止完成的虚拟谓词。0x1015555140x101ce42500x101b5c264
在最终波生成前的提示期间手动点击,可以让管理器在实体清空之后仍等待新的截止时间。仅仅清空草坪,并不会重置所保留的提示状态。
清空扫描对哪些僵尸应用例外?
实体标记检查之后,原生扫描有以下明确例外,并不存在一个通用的“本体 HP 为正”要求来替代它们。
其他符合条件的僵尸即使在草坪之外,也可以阻止胜利。死亡转换、移除请求,以及从 Board 列表中删除,也是不同时点。
只要摩登世界传送门引用仍可解析,其阻塞函数就返回真。最后一次释放之后仍保留下一次计划检查;该检查请求关闭,再由关闭动画回调移除传送门。因此,空队列不会立即清除该阻塞。传送门消失后,存活的子僵尸仍是独立阻塞因素。88传送门在移除前仍阻止完成GridItemZombiePortal 用于阻止完成的虚拟函数无条件返回真。普通释放器消耗最后一个队列条目后,仍会推进下次截止时间。之后的空队列检查开始关闭动画,由回调请求移除并使弱身份失效。队列耗尽与移除是不同状态。0x1001227340x100121a000x100121e44
传送门视图单独展示这一顺序,与普通波次推进区分。
失败 与 继续 关 卡 还 会 检查 另外 的 状态
普通失败模块要求 CanTrigger,并检查自己的状态/类型/标记条件。在未偏移分支中,声明的 Zombie 意味着
某个 Board 标记可以将阈值偏移 30,另一种模式还可以增加 Y 检查。负的生成波次标记本身并不是豁免条件。99普通失败边界模块先检查 CanTriggerZombieWin、虚拟状态谓词、实体标记及其他模式/类型条件,再将 X - 200 与配置阈值比较。正文给出未偏移情况;Board 标记可以移动阈值,另一种模式还可增加 Y 条件。资格辅助函数不要求生成波次标记为非负。0x10153839c0x1015386b4
胜利后,客户端发送结束关卡请求,先处理返回的进度记录,再继续。它不会简单地递增本地进度并假定成功。普通继续路径只在返回的已存进度加一小于 150 时加载下一份文件。随包 Boss 间隔为 5,因此 1–149 的序列包含 120 个普通关卡与 29 个 Boss 边界。1010返回进度与继续关卡边界成功的结束关卡响应先写入返回记录,再继续完成界面/事件。普通胜利路径随后只在已存进度加一小于 150 时加载下一份世界文件。文件名辅助函数使用有效的 BossInterval。这是所检查的继续关卡规则,并非对其他开始/跳关路径服务器准入的普遍断言。所有标准普通文件都声明 CanSaveGameState 为假。0x101ffc3e00x101d6cf7c0x101c360dc0x101d4a4e8
这个记录不是已保存的战场。普通定义声明 CanSave;无论进度,还是独立的已保存掉落计划,都不能证明会恢复之前的波次、实体或行历史。
注释
每条论断的依据:代码路径,以及追踪到它的原生地址。
- 1
动作完成后的生命值快照
波次开始时先调用所有动作回调,再查询符合条件的当前波次生命值并保存到 m_currentWaveTotalHealth。查询筛选生成波次标记与排除状态,并取得虚拟生命值。之后的检查将重新查询的生命值与保存的整数阈值比较。位置拒绝早于初始查询;查询之后的死亡可以降低剩余生命值,而不重写快照。
0x101ce76d80x102082abc0x101ce7ce00x1019b09c00x10199dfc80x101988e70 - 2
Float32 累加与有符号 int32 报告
基础读取函数使用 FCVTZS W0 转换 float32 的本体与头盔之和。波次查询将每个有符号贡献转换为 float32,加入 float32 累加器,再用 FCVTZS W0 转换最终和。非陷阱 FP 行为下,超范围的正数转换饱和到 2147483647。阈值使用截顶后的初始报告值。ARM64 算术检查覆盖转换边界、顺序舍入,以及 0.7、0.8、0.85 比例。
0x10199dfc80x102082abc0x101ce76d80x101ce7298 - 3
计时推进与大波延迟
普通计时状态的更新同时检查下次截止时间、距上一波的最小间隔,以及模式条件。生命值路径可以提前截止时间。大波提示状态在已有截止时间上加上 HugeWaveDelay。构造器时间值属于基线;WaveManager 属性还会尝试查询 DefaultWaveManagerProperties。
0x101ce73800x101ce7ce00x101ce6fe0 - 4
自动发出的手动式请求
下一波可见性从假变为真的事件检查 HasSkipNextWave 与边界条件,再调用手动请求处理器。普通 WaveManager 分支直接调用推进函数。普通可见性条件使用 nextWaveTime 减去生成间隔的一半。自动保护条件使用常规 FlagWaveInterval;此处没有独立检查最终波标记。
0x101581d5c0x101ce70940x101ce6e8c - 5
手动推进省略提示状态重置
普通按钮释放到达的请求只拒绝已结束的状态 8,随后直接推进。状态 2 的到期路径还会调用重置辅助函数,而手动路径省略此步。波次开始时写入新的截止时间,却不重置状态 2。该状态更新动作与进度,但省略普通 HP 提前触发与按钮可见性逻辑。最终波开始消息另行发出。受控的原始指令检查覆盖手动与计时的旗帜/最终波转换;外部服务与事件监听器使用桩处理。
0x101fde6b40x101581c900x101ce6e8c0x101ce60080x101ce75280x101583bf8 - 6
创建时的初始加速状态
实体创建检查档案选项、HastyOnStart、波次标记及模式排除条件,再施加状态 7。状态追踪器在后续调整前将移动速度因子翻倍。僵尸更新在 X <= 792 时清除该状态。这条创建分支不会在击退后重新施加。目录中四个明确为假的类型标记保留在参考数据中。
0x1015946a80x1019853a80x101999778 - 7
完成是注册谓词之间的逻辑与
模块管理器的汇总检查拒绝空谓词向量,并在第一个假结果处停止。WaveManager 注册结束状态检查;标准普通文件还注册 ZombiesDeadWinCon。后者扫描符合条件的僵尸指针,不限制为当前波次,应用明确的例外后,再检查网格物件集合 0x30 中阻止完成的虚拟谓词。
0x1015555140x101ce42500x101b5c264 - 8
传送门在移除前仍阻止完成
GridItemZombiePortal 用于阻止完成的虚拟函数无条件返回真。普通释放器消耗最后一个队列条目后,仍会推进下次截止时间。之后的空队列检查开始关闭动画,由回调请求移除并使弱身份失效。队列耗尽与移除是不同状态。
0x1001227340x100121a000x100121e44 - 9
普通失败边界
模块先检查 CanTriggerZombieWin、虚拟状态谓词、实体标记及其他模式/类型条件,再将 X - 200 与配置阈值比较。正文给出未偏移情况;Board 标记可以移动阈值,另一种模式还可增加 Y 条件。资格辅助函数不要求生成波次标记为非负。
0x10153839c0x1015386b4 - 10
返回进度与继续关卡边界
成功的结束关卡响应先写入返回记录,再继续完成界面/事件。普通胜利路径随后只在已存进度加一小于 150 时加载下一份世界文件。文件名辅助函数使用有效的 BossInterval。这是所检查的继续关卡规则,并非对其他开始/跳关路径服务器准入的普遍断言。所有标准普通文件都声明 CanSaveGameState 为假。
0x101ffc3e00x101d6cf7c0x101c360dc0x101d4a4e8