跳到正文

两个分配系统为之后的掉落事件提供输入。能量豆从每波配额开始,按指令顺序请求携带者;一般掉落从按条目保存的计划开始,按单个波次成本分配标记。计划数量或已接受标记,都还不是已经收集的奖励。

什么叫“符合条件的设置行”

当设置行的 MinLevel 不大于显示关卡数 LL 时,该行符合条件。生成器从全部符合条件的 FlagWaveSetupList 行中选择一行。其 FlagCount 给出能量豆数量的抽取次数,而非新版波次布局公式中的波次数或间隔。

MinLevelFlagCount
11
51
151
301
402
502

独立的 PlantfoodSetupList 提供抽取边界。其随包条目如下:

MinLevelMinPlantfoodPerFlagWaveMaxPlantfoodPerFlagWave
111
522
1522
3011
5011
5500

对于符合条件的能量豆设置行 I(L)I(L),两个边界都通过取最小值来归约:

a(L)=min⁡i∈I(L)MinPlantfoodPerFlagWave⁡i,b(L)=min⁡i∈I(L)MaxPlantfoodPerFlagWave⁡i.\begin{aligned} a(L)&=\min_{i\in I(L)}\operatorname{MinPlantfoodPerFlagWave}_i,\\ b(L)&=\min_{i\in I(L)}\operatorname{MaxPlantfoodPerFlagWave}_i. \end{aligned}

令 kk 等于选中的 FlagCount,计划总量为

Q=∑j=1k(a+uj mod (b−a+1)).Q=\sum_{j=1}^{k}\left(a+u_j\bmod(b-a+1)\right).

声明为 2 的行不会替代较早声明为 1 的行。两个有效边界一直保持为 1,直到第 55 关的行将它们降为零。第 49 关时,四个合格旗帜行要求抽取一次,另一行要求抽取两次,因此根据选中行不同,QQ 为 1 或 2。

分配按顺序访问常规旗帜边界,只要有余量,就各给一个单位。之后才将剩余单位放到随机选择的波次,允许重复。较短分组的最终波,不会仅因它是最终波就被插入常规边界遍历。第 49 关的 9 波方案只有一个常规边界,即第 5 波:第一个单位分给该波,可能存在的第二个分给随机选择的波次。最终第 9 波在这次分配中没有优先权。

每波的分配被复制到其普通动作的 AdditionalPlantfood。这是动作配额;独立旗帜僵尸动作有自己的默认零配额。生成器将 DynamicPlantfood 和 SpawnPlantName 留空。11能量豆数量的构建构建器从所有符合条件的 FlagWaveSetupList 行中抽取 FlagCount。它分别对符合条件的 PlantfoodSetupList 最小值和最大值取最小值,再把所得数量分配到波次。转换流程将每波数量复制到 AdditionalPlantfood。生成的普通动作将 DynamicPlantfood 与 SpawnPlantName 留空。0x101ab68400x101ce8a54

请求可以消耗配额,却仍然失败

创建器按顺序扫描普通指令。只要还有配额,CanSpawnPlantFood: true 就消耗一个单位,并请求在新实体上标记携带者。属性为假则跳过,不消耗单位。这里没有额外的随机携带者选择过程。

标记函数随后应用档案与模式条件。在 DangerRoom 中,IsA(ZombieGargantuar) 会拒绝真值请求,包括子类。这是运行时类检查,与阵容选择中的高成本检查不同。请求已经被消耗,调用方没有成功结果、退还或重试分支。22已消耗的请求仍可能被拒绝有序创建循环在调用实体标记函数之前减少配额。CanSpawnPlantFood 为假时跳过消耗,为真时消耗一个单位。标记函数另外检查档案/模式条件,并在 DangerRoom 中拒绝 IsA(ZombieGargantuar)。它不返回成功结果,调用方没有退还或重试分支。属性检查与运行时类检查相互独立。0x1014c40c00x1014c43240x1019af834

配额为 1 时的输入顺序配额扫描被接受的携带者
eighties_gargantuar_danger、eighties巨人声明为假;请求到达基础僵尸eighties
cowboy_gargantuar_danger、cowboy巨人声明为真,消耗请求后被类条件拒绝无
cowboy、cowboy_gargantuar_danger基础僵尸先消耗请求cowboy

Jam 替换早于这次扫描。它保留数值配额,却改变接收请求的类型与顺序;此时不存在需要保留的 Jam 替换前实体标记。动作结束后仍剩余的配额,不会由这个循环转交给其他动作。传送门子僵尸使用独立释放器。

请求同样早于位置钩子。在那里被拒绝的国王或渔夫,可能已经拥有接受的标记。尽管死亡/移除方式不同,两条拒绝路径都可以到达普通掉落处理。

后续事件请求拾取物

基础僵尸掉落方法先发出 Board 事件,再设置已处理掉落标记。监听器要求事件尚未处理、m_canDropLoot、hasplantfood 状态,以及相应模式许可。

在普通的空 SpawnPlantName 分支中,监听器清除携带状态,并请求 plantfood 拾取物。非空名称改走种子包分支。基础移除同样到达掉落分发器,因此移除本身并不意味着没有掉落。33从携带状态到拾取物工厂基础掉落分发在设置已处理掉落标记之前发出 Board 事件。监听器检查该标记、m_canDropLoot、hasplantfood 和模式条件。普通空名称分支清除携带状态并调用拾取物工厂。基础移除回调也会到达掉落分发;移除本身并不意味着没有掉落。0x1019a5dac0x10158157c0x101588a24

携带者视图分别展示属性检查、已消耗请求、已接受标记与拾取物事件。重排同样两条指令,可以在不改变原配额的情况下改变结果。

顺序 1

  1. 重金属巨人僵尸(无尽)eighties_gargantuar_danger

    剩 1 个

    false

    跳过,不消耗

  2. 摇滚僵尸eighties

    剩 1 个

    true

    消耗一个:1 → 0

    接受

    设置携带者标记

    plantfood

    请求拾取物

顺序 2

  1. 西部巨人僵尸(无尽)cowboy_gargantuar_danger

    剩 1 个

    true

    消耗一个:1 → 0

    拒绝

    单位仍已耗去

  2. 牛仔僵尸cowboy

    已用完

    不读取属性

    true

顺序 3

  1. 牛仔僵尸cowboy

    剩 1 个

    true

    消耗一个:1 → 0

    接受

    设置携带者标记

    plantfood

    请求拾取物

  2. 西部巨人僵尸(无尽)cowboy_gargantuar_danger

    已用完

    不读取属性

    true

图版 7.1上表的三种顺序,能量豆配额为 1。创建器按顺序检查每条指令:是否还有单位,属性是否为 true,标记能否通过类别检查。三项都通过的路径才到达拾取物。携带者:eighties · 无 · cowboy。

一般掉落推进按条目保存的计划

波次安装在世界后处理之后、运行时 WaveManager 重新播种之前,执行一般掉落流程。配置必须存在、处于启用状态,且收集到的波次总成本为正。在 LevelLength = -1 时,它根据已安装的 NN 波估计规划长度:

λ(N)=N−103+4.\lambda(N)=\frac{N-10}{3}+4.

运算先使用 float32,再扩展为 double。明确的 LevelLength 可以替代该估计。这些是规划单位,并非战斗耗时。

合格掉落表行必须通过 World 和 EnabledAfter 检查。世界标签来自精确的世界地图关卡节点查询,并不简单等于场景世界名。所检查的地图集合没有匹配的 DangerRoom 节点,因此留下空标签;限定世界的行无法匹配。七个不限世界的回退行仍要求 tutorial4 进度:

UniqueIdTypeMin–MaxPeriod
Silver1SilverCoin1–31
Gold1GoldCoin1–120
Gold2GoldCoin1–120
Gold3GoldCoin1–330
Gold4GoldCoin1–330
Diamond1Diamond1–130
Diamond2Diamond1–140

每个合格行拥有以 UniqueId 为键的保存记录。因此,即使类型与周期相同,两个金币行仍保留独立历史。以 CC 表示 LevelLengthsPlayed,DD 表示 NextDropTime,SS 表示 NextScheduleTime。新记录初始为 C=0C=0、D=∞D=\infty、S=0S=0;其中 ∞\infty 代表没有待处理掉落的哨兵值。

每次规划调用:

  1. 把 λ\lambda 加到 CC。
  2. 若 D<CD<C,从包含两端的 Min–Max 中抽取数量,追加相应数量的掉落代码,再把 DD 重置为哨兵值。
  3. 若 S<CS<C,在 Period 内选择相位,把 DD 设为原来的 SS 加上该相位,再把 Period 加到 SS。
  4. 只要仍需要另一轮安排,就重复掉落/安排处理。

两个比较均为严格比较。新安排的掉落,可能在同一次规划调用中已经到期,并在下一轮处理。相等时,需要等待以后累积更多长度。相位/数量抽取消耗全局 RNG,管理器随后请求保存更新记录。44按条目保存的计划状态安装器在世界后处理之后、运行时 WaveManager 重新播种之前调用一般掉落规划。符合条件的表格行保留各自的 UniqueId 历史。规划器推进 LevelLengthsPlayed,处理严格到期的掉落与计划,并请求保存记录。数量与相位抽取消耗全局随机数。世界/档案资格和有效表格覆盖值也是输入。0x101ce66dc0x101a8b5e80x101a8b124

这解释了为什么当前关卡与一个生成种子无法确定计划列表:有效表条目、档案资格、已保存历史,以及较早的全局抽取都参与其中。

成本为单个指令提供权重

流程收集普通和独立旗帜生成器的类型向量,并创建平行、初始填零的掉落数组。传送门子僵尸尚未存在于这些生成器向量中,不是此流程中的条目。

对于每个非零掉落代码,成本为 cic_i 的未标记指令 ii 在抽签袋中的名义份额为

ci∑j∈Ucj,\frac{c_i}{\sum_{j\in U}c_j},

其中 UU 是剩余未标记集合。按累积成本抽取一条指令,分配标记,并从之后的抽取中移除其成本。分配不放回;没有可选的剩余候选时停止。它使用 WavePointCost,而非 Weight、HP、实体等级或首领生命值。55按单个成本加权的不放回分配该流程收集 ZombieSpawnerAction 类型向量并创建平行掉落数组。非零掉落代码按解析后的 WavePointCost 累积值分配;每个已标记指令及其成本不再参与后续抽取。标记不会重排指令,也不改变等级、行、首领或能量豆字段。实体创建之后把注释复制为实体保存的掉落代码。0x101ce66dc0x1014c513c0x1019afe38

由于流程在 Jam 之后,它使用替换后的成本。注释数组不改变指令顺序、行、等级、首领字段或能量豆配额。创建时,每条指令对应索引上的标记被复制到其实体。

基础掉落分发器随后根据保存代码请求拾取物别名,并受其掉落/状态条件约束:

代码注册枚举请求拾取物
1SilverCoincoin_silver
2GoldCoincoin_gold
3Diamondcoin_gold

代码 4–13 不在这个分发器中创建拾取物。因此,不能只凭代码 3 的枚举名称,推断生成别名或最终物品栏入账。66枚举标签与实际分发别名注册代码将 1、2、3 命名为 SilverCoin、GoldCoin、Diamond。所检查的基础分发函数为 1 请求 coin_silver,为 2 和 3 都请求 coin_gold。代码 4–13 不通过这个分发函数创建拾取物。这些是请求的拾取物别名,不能根据枚举标签推断物品栏入账。0x101a899940x1019a5dac0x101a8b78c

注释

每条论断的依据:代码路径,以及追踪到它的原生地址。

  1. 1

    能量豆数量的构建

    构建器从所有符合条件的 FlagWaveSetupList 行中抽取 FlagCount。它分别对符合条件的 PlantfoodSetupList 最小值和最大值取最小值,再把所得数量分配到波次。转换流程将每波数量复制到 AdditionalPlantfood。生成的普通动作将 DynamicPlantfood 与 SpawnPlantName 留空。

    0x101ab68400x101ce8a54
  2. 2

    已消耗的请求仍可能被拒绝

    有序创建循环在调用实体标记函数之前减少配额。CanSpawnPlantFood 为假时跳过消耗,为真时消耗一个单位。标记函数另外检查档案/模式条件,并在 DangerRoom 中拒绝 IsA(ZombieGargantuar)。它不返回成功结果,调用方没有退还或重试分支。属性检查与运行时类检查相互独立。

    0x1014c40c00x1014c43240x1019af834
  3. 3

    从携带状态到拾取物工厂

    基础掉落分发在设置已处理掉落标记之前发出 Board 事件。监听器检查该标记、m_canDropLoot、hasplantfood 和模式条件。普通空名称分支清除携带状态并调用拾取物工厂。基础移除回调也会到达掉落分发;移除本身并不意味着没有掉落。

    0x1019a5dac0x10158157c0x101588a24
  4. 4

    按条目保存的计划状态

    安装器在世界后处理之后、运行时 WaveManager 重新播种之前调用一般掉落规划。符合条件的表格行保留各自的 UniqueId 历史。规划器推进 LevelLengthsPlayed,处理严格到期的掉落与计划,并请求保存记录。数量与相位抽取消耗全局随机数。世界/档案资格和有效表格覆盖值也是输入。

    0x101ce66dc0x101a8b5e80x101a8b124
  5. 5

    按单个成本加权的不放回分配

    该流程收集 ZombieSpawnerAction 类型向量并创建平行掉落数组。非零掉落代码按解析后的 WavePointCost 累积值分配;每个已标记指令及其成本不再参与后续抽取。标记不会重排指令,也不改变等级、行、首领或能量豆字段。实体创建之后把注释复制为实体保存的掉落代码。

    0x101ce66dc0x1014c513c0x1019afe38
  6. 6

    枚举标签与实际分发别名

    注册代码将 1、2、3 命名为 SilverCoin、GoldCoin、Diamond。所检查的基础分发函数为 1 请求 coin_silver,为 2 和 3 都请求 coin_gold。代码 4–13 不通过这个分发函数创建拾取物。这些是请求的拾取物别名,不能根据枚举标签推断物品栏入账。

    0x101a899940x1019a5dac0x101a8b78c