第 03 篇

不同世界如何修改方案

替换、额外动作与世界特有的系统。

共同阵容构建之后,世界仍可以改变方案。摇滚年代替换普通指令;恐龙危机和摩登世界添加独立动作;蒸汽时代则在更晚的设置阶段安装场地系统。要理解最终战斗,需要知道事件安排、每个事件执行的操作,以及这些结果进入 Board 的先后顺序。

先抽取端点,再插值

多个设计器使用同一个辅助函数。对于关卡边界为 L0,L1L_0,L_1 的参数,它先从包含两端的低关卡和高关卡端点范围中抽取整数 aabb,再计算

α(L)=clamp(LL0L1L0,0,1),v(L)=trunc(a+α(L)(ba)).\begin{aligned} \alpha(L)&=\operatorname{clamp}\left(\frac{L-L_0}{L_1-L_0},0,1\right),\\ v(L)&=\operatorname{trunc}\bigl(a+\alpha(L)(b-a)\bigr). \end{aligned}

原生运算使用 float32 与融合乘加。固定端点仍消耗一次抽取;即使限制后的比例为 0 或 1,也会抽取两个端点。因此,端点范围表定义的是先抽取、再插值,而不是在两个插值后的边界之间均匀抽取。

摇滚年代:安排音乐并替换指令

DangerRoomJamDesigner 在普通填充之后运行,使用全局 RNG。它在战斗创建这些僵尸之前,就将音乐事件准备到波次属性中。

先选择音乐集合

第 7 关之前,候选为 Pop、Punk、Rap 和 8-bit。Metal 从第 7 关加入。所需的不同音乐数量从第 1 关的 2 插值到第 15 关的 5,并受合格候选数量限制。设计器重复抽取候选,直到拥有足够多的不同类型。重复结果被丢弃,但仍消耗该次随机抽取。

之后,每个事件都从这个完整子集中抽取。连续事件可以选择相同音乐。 子集选择不重复,不代表事件序列也不重复。jam_ballad 出现在更广泛的音乐列表中,但不属于这份无尽候选列表。

再选择事件波次

音乐安排独立于第 1 章中的旗帜间隔。令 wjw_j 表示第 jj 个事件从零开始的波次索引:

w0=Ifirst(L),wj+1=wj+Igap(L).w_0=I_{\mathrm{first}}(L),\qquad w_{j+1}=w_j+I_{\mathrm{gap}}(L).

每个 II 都是一次新的端点抽取插值,使用关卡边界 1–15。在 wj<N(L)w_j<N(L) 时继续添加事件。

参数第 1 关端点第 15 关及以后端点
不同音乐类型数量25
首次事件,从零开始的波次索引3–41–2
后续事件间隔,单位为波4–52–3

因此,低端点的首个事件位于玩家视角第 4–5 波,高端点则位于第 2–3 波。事件间隔按波计数,不按秒;每个事件之后的间隔都会重新抽取。

一个事件改变什么

对于一次事件,设计器从下表选择一种替换类型。Rap 为整个事件选择一次,而不是为每条被替换指令单独选择。

通知事件替换类型
jam_popeighties_glitter
jam_punkeighties_punk
jam_rapeighties_mceighties_breakdancer
jam_8biteighties_arcade
jam_metaleighties_gargantuar_danger

替换数量使用独立的关卡范围 1–50,端点范围为 1–2 和 5–7。结果不超过当前指令数。每次移除时,设计器从剩余索引中选择一个,保存该指令的等级,将最后一条指令移入其槽位,再缩短向量。之后,使用保存的等级,追加选定替换类型的新指令。

只有等级被带入新指令。新指令的其他字段采用默认值,包括为假的首领标记。未选中指令保留自身字段,但交换移除可以改变其顺序。最终数量与等级多重集保持不变,总成本和首领标记则可能变化。流程不重新执行普通预算检查,因此 Metal 可以加入巨人,即使替换成本超过原始额度。

事件名被追加到 NotificationEvents。运行时,动作先创建并放置整批实体,再发出这些通知。替换早已在生成阶段决定;通知送达,才是音乐事件之后进入 Board 的时点。

AdditionalPlantfood 保持不变。其携带者请求之后才根据修改后的顺序和类型分配。一般掉落分配也在之后运行,使用替换后的成本。最后,波次生命值快照在位置处理后测量最终符合条件的实体。这是同一个替换流程对三个后续环节产生的不同影响。

恐龙危机:在阵容之外追加事件

候选类型为 raptorstegopterotyrannoankylo。设计器通过重复抽取不同类型形成子集,再为每个恐龙事件选择一种类型。端点插值使用关卡边界 1–20。

参数第 1 关端点第 20 关及以后端点
选中的恐龙类型25
首次事件,从零开始的波次索引3–42–3
后续事件间隔,单位为波3–41–2
事件中的恐龙数量1–23–4

首次索引与后续间隔共同定义事件序列,方式与上文相同。事件发生的波次中,请求数量的恐龙动作被追加到普通僵尸动作旁。行号从 0–4 的可消耗列表中抽取;若剩余条目不足以供下一个事件使用,就补充列表。这些选择消耗全局 RNG,不花费普通僵尸预算。

摩登世界:事件创建带有独立队列的传送门

回退候选包含十个家族:摇滚年代、恐龙危机、失落之城、冰河世界、巨浪沙滩、黑暗时代、未来世界、狂野西部、古埃及和海盗港湾。它们的初始选择权重均为 1.0。设计器不放回地选择家族,子集大小从第 1 关的 1 增长到第 30 关的 4。每个传送门事件波从这个子集中选择一个家族。

事件参数第 1 关端点第 30 关及以后端点
首次事件,从零开始的波次索引42–3
后续事件间隔,单位为波42
一次事件中的传送门数量13–4
生成列,从零开始85–6
计算出的每门僵尸数量1–23–4
计算出的列表起始索引00
计算出的列表结束索引03

行号从 0–4 中不放回抽取,并按需补充。家族与行选择使用传入的设计器 RNG;端点插值消耗全局 RNG。

最后三个计算值没有被普通 SpawnModernPortalsWaveAction 传递。它只传递传送门家族和位置,让运行时数量/起始/结束覆盖值保持默认。这些被丢弃的计算仍消耗了随机抽取。

因此,传送门复制家族的完整四槽列表,再通过导入的 C++ RNG 机制打乱。重复名称仍然是独立槽位。古埃及的源列表为 raexplorerexplorerpharaoh:包含两个 Explorer 槽位,而非一个。下方视图可以检查全部十个家族。

开启、释放与关闭

首次请求截止时间为创建时刻加上随机偏移;该偏移在零与一个从 10–12 秒区间抽出的值之间抽取。释放还要等待开启完成。每个后续间隔加在前一次计划截止时间上,而不是简单地加在延迟发生的实际释放时刻上。

每个释放出的子僵尸获得波次标记 5-5。它不计入普通当前波次生命值,也不获得初始场外加速,但仍参与独立的胜利和失败谓词。其请求等级边界来自共享 DangerRoom 曲线,但使用全局浮点抽取进行选择,而非普通指令的整数余数比较。

最后一个槽位释放后,传送门仍会安排下一次到期检查。之后的检查发现空队列,才开始关闭;关闭动画回调随后请求移除。在移除之前,传送门自身仍是完成阻塞因素,与存活的子僵尸相互独立。

蒸汽时代:固定场地系统与独立时钟

蒸汽时代使用更晚的设置钩子。令 α=clamp((L1)/99,0,1)\alpha=\operatorname{clamp}((L-1)/99,0,1),其数量为

nsmoke=3α,npipe=5α.n_{\mathrm{smoke}}=\lfloor3\alpha\rfloor,\qquad n_{\mathrm{pipe}}=\lfloor5\alpha\rfloor.

烟雾孔数量在第 34、67、100 关首次达到 1、2、3;管道数量在第 21、41、61、81、100 关达到 1–5。位置固定:玩家视角中,烟雾位于第 6 列,从第 2 行起;管道从第 7 列通往第 5 列,从第 1 行起。

首次烟雾启动参数从 15 插值到 30 秒。烟雾伤害与管道堵塞伤害都从 30 插值到 100,使用管道命名的伤害字段。烟雾启动调用使用字段的顺序,与 MinMax 名称暗示的顺序相反。

烟雾等待事件

开始调用时,首次预警截止时间为 t+3t+3;首次喷发截止时间则独立设为 t+StartTimet+\operatorname{StartTime}。喷发动画完成才激活烟雾。活动期间,累计值严格大于 1 秒时执行一次伤害检查,再减去 1 秒。检查在烟雾孔所在格及周围八格中,各选择一个植物目标,而非独立伤害每一个叠放层。

活动烟雾不会自动在五秒后到期。必须先完成 blow_offabsorb 等清除路径。其移除事件开始冷却:下次预警为清除时刻 + 5 秒,下次喷发再晚 3 秒,尚未计入额外延迟。所检查的移除事件没有携带所属烟雾孔参数,而是广播给已注册的烟雾孔处理器。

管道保留同一批实体

进入要求实体位于入口格、X 坐标与入口距离严格小于 0.5、运行时体型为 small,并通过包含 CanBeLaunchedByPlants 在内的共享能力/状态检查。蒸汽时代矿工为 mid,巨人为 big,因此不能通过这个体型条件。

普通路径的两列距离产生 2 秒时长参数,但实体截止时间分别为 t+1t+1t+2t+2t+3t+3。它从地下阶段截止时间起使用出口位置,只有严格超过最终截止时间才完成。多个僵尸可以同时处于运输中;这并非一次只服务一个对象的队列。

作为阻挡植物的平顶菇(flattenedshroom)可以延长地下与完成截止时间;其随包 BlockTime 为 12 秒。只要仍有运输对象引用,每次更新就对每株阻挡植物施加一次 DamagePerSecond 乘以游戏时间增量的伤害,不按运输僵尸数量重复施加。运输保留原等级与波次标记,基础当前波次生命值查询也不排除 ZS_StuckInGround 状态。

证据注释 /