关于出怪列表的填充:级别容量上限、固定出怪、无限制出怪……
本文在多个平台发布,不同平台内容有细微差别:
植吧:https://tieba.baidu.com/p/8229511229
Word文档:https://docs.qq.com/document/DRGRDRWpNV2Vjdm9I
Excel表格:https://docs.qq.com/document/DRGxPVVlZSnRKdXdC
大家应该都看过PT站上的资料吧,那个有些问题的。


在探究冒险模式和各个非EL关卡的过程中,发现“级别容量上限”并非在所有关卡中都符合这一规律。借助“级别上限”,本文将对各关出怪列表填充的机制进行简单的分析。
注1:以下内容未使用反汇编,全部使用修改器+不完全归纳得出,加上up和宝开都存在犯傻的可能,因此并不能保证绝对正确,大家有发现问题欢迎反应。
注2:本文全部使用英文原版1.0.0.1051,对其他版本不负责。

目录
零、推荐阅读
一、辅助工具说明
二、级别容量上限
2.1 第一类
2.2 第二类
2.3 混合类
2.4 特殊说明
2.4.1 一周目1-1~1-3、1-5
2.4.2 谁笑到最后
2.4.3 一/二周目5-5、蹦极闪电战
2.5 关卡一览
三、固定出怪
3.1 (冒险模式)新僵尸
3.2 (冒险模式)最后一波出所有僵尸
3.3 (所有模式)旗帜波出普僵旗帜
3.4 特殊情况
3.4.1 一周目1-1
3.4.2 二周目1-5
3.4.3 一/二周目5-5、蹦极闪电战
3.4.4 植物僵尸、植物僵尸2
3.4.5 你看,他们像柱子一样
3.4.6 谁笑到最后
3.5 顺序... 15
四、无限制出怪
4.1 几则实验
4.2 出怪规律
4.3 具体列表
4.3.1 跳跳舞会
4.3.2 空袭
4.3.3 雪橇区
五、下期预告

零、推荐阅读
标题:这两天研究了一下PVZ的出怪机制
链接:https://tieba.baidu.com/p/2306159144
标题:【火星向】分析冒险6-49为什么有豌豆射手僵尸
链接:https://tieba.baidu.com/p/6134448446
标题:刷怪相关数据记录/研究
链接:https://tieba.baidu.com/p/6437868025
标题:【无尽开局出怪规律科普】你知道多少轮以后出怪饱和吗?
链接:https://tieba.baidu.com/p/7861483105
PT站百科
链接:https://pvz.tools/wiki/#出怪规律

一、辅助工具说明
使用到的辅助工具有:
1. PT:可以修改出怪种类(会默认选择普僵);可以显示w1~20的出怪种类和数量(PTK只能显示SE的出怪)。
2. v1.9:可以修改出怪种类(可以不选择普僵)。
3. WPF:可以显示出怪列表;可以修改出怪种类(会默认选择普僵);可以显示所有波的具体出怪列表(即在列表中的顺序也能看到)。
其他跳关、自收、后台、倍速等功能与本文关系不大,略去。
关于辅助工具的一些事:
1. 正常状态下出怪列表中普僵似乎是不可更改的?

不过v1.9的确可以做到不选普僵,并且会导致一个神奇的现象:
正常来说只有普僵和豌豆级别是1(权重为0的不计);如果出怪没有这两种僵尸,可能因为前几波级别上限为1的就没法填了,会把出怪列表中序号最小的僵尸的级别变为1。
这个推测是v1.9的效果而非游戏本身的机制:如果用WPF挑一个无普僵、无豌豆关,并修改出怪种类,得到的并不是这样的效果(下文“无限制出怪”会讲);如果挑的是无普僵、有豌豆关,会直接闪退。
//(来自xiao_He)后来发现就是作者为了防止闪退故意添加的:

2. 关于“波数”,绝大部分地方都是从1开始的,即我们平时所说的第x波,但是(目前发现)有两处例外,是从0开始的(即内存中的数值,没有+1):
一处是ShowMe的“僵尸所在波数”:

还有一处是级别容量上限公式中的“当前波数”:
可以用w3验证一下:
w3(3):int(int(3*0.8)/2)+1=2
w3(2):int(int(2*0.8)/2)+1=1
下文“波数”均指平时所说、从1开始的波数。
//(来自uint8_t)补充:
/*
出怪列表可以自行在内存中读取,但是未填充到的部分会有垃圾数据残留在里面。因此要在同时读取每波的总出怪数。
地址表:十六进制[[[6a9ec0h]+768h]+ 6b4h],从这个地址开始的2000个的数据,每个数据是unsigned int。其中存放的是僵尸的编号,每50个数组一组,为一波的出怪,共可容纳40波。
*/
/*
(来自xiao_He)有时候用PT读取冒险的出怪会看到w10以后群魔乱舞,就是因为之前打开其他关卡留下的出怪记录没有删去。
另外游戏到底是如何得知本次出怪列表取到哪一位的,暂不知晓。
*/

二、级别容量上限
不考虑多次选卡,PT站的那条公式可以简化为:
用这个公式可以得到w20的级别容量上限是20,但是实际上发现不全是这样,哪怕是大家最最最最最熟悉的生存无尽:

w20:12+1+2*2=17≠20。
看来需要重新统计一下了……
咳,先说一下统计级别容量上限的方法。第一种是脚本统计。
第二种,针对不会写脚本的人,前20w可以将出怪设置为只有普僵,再用PT查看,这样普僵的数量就是级别容量上限(因为特殊出怪,其实还需要加上一些,但反正是轻松了不少);
20w以后PT就不管用了,在PT更新之前只能用WPF读取,WPF没有直接的统计,需要一个个数,推荐出怪设置为普僵和巨人(白/红眼均可),普僵每只级别1、巨人每只级别10。
经探索发现游戏中有两类级别容量上限:
第一类公式:每波容量上限 = int(int((当前波数) * 0.67~0.68) / 2) + 1。

第二类公式:每波容量上限 = int(int((当前波数) * 0. 8) / 2) + 1。

一个很简单的分辨方法:看开头,如果是aaabbbccc就是第一类,如果是aaabbccc就是第二类。
此外还有将两类混合起来的混合类,还有若干变式,下面详解:
2.1 第一类
基础公式:每波容量上限 = int(int((当前波数) * 0.67~0.68) / 2) + 1,大波再*2.5。

那个参数是0.67或0.68得到的结论是一样的:

也可以简单地记为“每3波增加1”。
此外部分关卡会在此基础上进行翻倍,普通波会全部翻x倍;旗帜波则是加法,w10/20/30每加一倍分别增加5/9/16,具体公式尚未找到。
普通波翻2倍:

适用关卡:一周目5-5、蹦极闪电战、隐形食脑者、保护传送门、你能挖了它吗。
普通波翻3倍:

适用关卡:一周目x-10。
普通波翻4倍:

适用关卡:一周目1-5、二周目1-5、坚果保龄球、坚果保龄球艺术锦标赛、一周目3-5、小僵尸大麻烦。
普通波翻6倍:

适用关卡:你看,他们像柱子一样
2.2 第二类
基础公式:每波容量上限 = int(int((当前波数) * 0.8) / 2) + 1,大波再*2.5。

也可以简单地记为“每10w的第1、4、6、9波增加1”。
翻倍后如下,旗帜波w10/20/30每加一倍分别增加是5/11/21。
普通波翻2倍:

适用关卡:二周目5-5。
普通波翻3倍:

适用关卡:二周目x-10。
普通波翻4倍:

适用关卡:二周目3-5。
2.3 混合类
生存模式(包括简单、困难、无尽),第一次选卡(1~20w)按照第一类公式出怪,之后(>w20)按照第二类公式出怪。
2.4 特殊说明
2.4.1 一周目1-1~1-3、1-5
一周目1-1:

一周目1-2:

一周目1-3:

一周目1-5:

其实都是符合前面的结论的,只是比较特殊就单拿出来了,1-1的w4没有旗帜僵尸、容量上限也没有*2.5(否则就是2*2.5=5了)。
2.4.2 谁笑到最后

显然是从常规第二类的w11开始的。
2.4.3 一/二周目5-5、蹦极闪电战
见下文“固定出怪”部分。
2.5 关卡一览
其实前面写过一遍了……再放在一起写一遍,方便查阅。
具体关卡和对应的公式参数、倍数如下:


三、固定出怪
使用v1.9将出怪种类设置为原本不会出现的僵尸,就可以得到每一波的“固定出怪”。
绝大多数情况下,这些“固定出怪”满足以下特点:
不管“固定出怪”的僵尸在不在本关出怪种类中,总是会先填充进出怪列表。此时如果已经达到或超过级别容量上限,则不会继续出怪(一周目很多关卡的w11和w20光是把固定出怪填完就满了);若是没有达到,则会继续填充。
至于为什么是“绝大多数情况下”,因为有一个例外,5-5和蹦极闪电战。
测试方法:使用v1.9将出怪种类设置为本关不会出现的僵尸(如红眼),剩下还黏在出怪列表中的就是固定出怪了。
固定出怪大致分为4种情况:
(冒险模式)新僵尸
(冒险模式)最后一波出所有僵尸
(所有模式)旗帜波出普僵旗帜
特殊情况
3.1 (冒险模式)新僵尸
一、二周目都有,本关如果有新出的僵尸,会选择其中序号最小的(如3-6新出冰车和雪橇小队,会选择冰车)进行填充,在第 总波数/2+1 波和最后一波各有一只,特例如下:
气球、矿工固定于w7和w20(Final Wave)各出一只,一、二周目都是,而不是第 总波数/2+1 波;
6-49会出豌豆射手僵尸;//(来自uint8_t)实际上这不是“特例”,只是由于豌豆编号的特殊性导致的bug,豌豆的编号正好在6-49,符合规律((( //(来自xiao_He)确实比较特殊嘛。
雪人只会固定出现于二周目4-10的w16,w30没有,且击杀后退出重进一次就不会出现了(重进两次就可以了)。
一、二周目1-1都不会因为这个固定于w3和w11生成普僵,1-3的路障是符合的。
话说红眼会不会出现啊?
3.2 (冒险模式)最后一波出所有僵尸
一、二周目都有,迷你游戏和生存没有,最后一波会先把本关出怪种类列表中(除雪人僵尸外)所有(权重不为0的)僵尸都出一只。
当然这会与“新僵尸”和“旗帜波出普僵旗帜”重叠,重叠起来就不用再出一遍了。
并且从6-49可以看出,新僵尸会出在最后一波是“新僵尸”导致的,而不是(至少不只是)“最后一波出所有僵尸”,因为豌豆射手僵尸并不在出怪种类列表中,却仍然会出现在最后一波。
顺便一提,使用WPF修改出怪种类列表,再用PT修改出怪种类,可以发现最后一波的固定出怪也会发生改变。推测是两种修改器改的地方不同,具体什么原因就不清楚了。
3.3 (所有模式)旗帜波出普僵旗帜
大名鼎鼎的“大波固定出8普僵1旗帜”,实际上稍微复杂一点。这个和级别容量上限是有关的,具体公式推不出来。
第一类上限:

第二类上限:

这也是个快速判断级别容量上限类别的方法……
另外,部分迷你游戏在w40后会重复w40的出怪,我称之为w41+,w41+固定出9普僵,就是那个旗帜换成了普僵。
3.4 特殊情况
3.4.1 一周目1-1
一共4波,上限分别为1,1,1,2,且w4固定出1普僵,至于这个普僵具体属于“旗帜波出普僵旗帜”还是“最后一波出所有僵尸”,倾向于后者,因为没出旗帜。
当然这个不需要纠结,因为1-1只会出普僵嘛。
3.4.2 二周目1-5
出怪列表中有普僵、路障、撑杆、铁桶、读报,但是最后一波固定出怪只有普僵、旗帜、路障。
3.4.3 一/二周目5-5、蹦极闪电战
除最后一波外,前面的旗帜波固定出且只出5只蹦极,普僵旗帜都不出了。
最后一波先填冲5只蹦极,再填充普僵旗帜等出怪:

这是隐形食脑者的出怪,一类2倍:

w20级别容量上限26。
这是一周目5-5的出怪,一类2倍:

w20不计蹦极的级别容量上限:15+1+2+4+4=26。
可见蹦极根本不占级别。
再看蹦极闪电战,一类2倍,共30w:

5只蹦极的总级别5*4=20<26,即使容量没有填满(实际上前面有说,蹦极根本不占级别),也不会生成其他僵尸。
5-5最后一波照常所有僵尸固定出1只,最后一波普僵、旗帜照出,空降三人组照出不误。
3.4.4 植物僵尸、植物僵尸2
普僵旗帜都不出了,没有任何固定出怪。
3.4.5 你看,他们像柱子一样
w6/16/26:先固定出10扶梯,(如果没填满的话)再出其他僵尸;
w9/19/29:先固定出10小丑,(如果没填满的话)再出其他僵尸;
w10:4普僵+1旗帜;
w20:7普僵+1旗帜+3巨人;
w30:8普僵+1旗帜+5巨人。
实际游戏中,开场就已经是w9了,会从w10开始出怪,然后w16固定出且只出10扶梯,w19起就会有其他僵尸了。

另外,巨人在出怪列表中的位置是在旗帜之后的:

3.4.6 谁笑到最后
总是固定出8普僵+1旗帜……其实完全符合前面的结论的。
3.5 顺序
如图,一周目1-8:

(蹦极闪电战的蹦极)→普僵→旗帜→(柱子关的巨人,与后面两条具体顺序不明)→新僵尸→所有僵尸。
“所有僵尸”这一栏应该是按照僵尸序号的,图为一周目5-9:

最后提一句,使用v1.9设置无普僵出怪,设置的出怪级别会变为1,但是固定出怪中的该种僵尸仍是正常的,因此推荐设置为关卡内不会出现的僵尸(如红眼):



四、无限制出怪
对于出怪种类列表中没有级别为1且权重不为0的僵尸的关卡(就称为“无普僵关”吧),使用的是另一套出怪方式,经验证应该就是WPF中的“无限制出怪”。
4.1 几则实验
实验一:
使用WPF将植物僵尸的出怪设置为扶梯+投石车,会闪退;
将植物僵尸的出怪设置为豌豆+投石车,可以正常进行;
将雪橇区的出怪设置为扶梯+投石车,可以正常进行。

结论:植物僵尸并不属于“无普僵关”,虽然它的确没有普僵。
实验二:
在选卡界面,使用WPF更改出怪,当前界面不会发生改变,退出重进后会改变;
在选卡界面,使用PT/PTK/v1.9更改出怪,当前界面发生变化,退出重进后仍是改变前的样子。
结论(推测):游戏中有两套“出怪种类列表”,一套与对应关卡绑定(WPF改变的),一套决定当前的出怪(PT改变的)。这个应该是现有结论了吧……
实验三:
正常打开跳跳舞会,用PT观察出怪:

使用v1.9将出怪列表设置为只有跳跳,用PT观察出怪:

发现两者不同(开头就有提到,v1.9造成的这一效果应该是独属于修改器的bug),再使用WPF修改,发现出怪正常。
结论:无普僵关并不按照常规的“自然出怪”进行,v1.9设置出怪种类+使用自然出怪一条龙服务导致出错,WPF只设置出怪种类而正常。
4.2 出怪规律
相比于自然出怪,无限制出怪有两处不同:
各波的级别容量上限和僵尸的级别均未改变,改变的仅仅是出怪方式:
当剩余级别容量>0时,可以加入任何僵尸(原本需要加入僵尸后剩余级别容量仍然≥0),直至剩余级别容量≤0,停止填充。
出怪不受僵尸阶数限制。
下面再把具体出怪情况列一下:
4.3 具体列表
4.3.1 跳跳舞会

4.3.2 空袭

(PT可以用就不手动输了。)
4.3.3 雪橇区
这个就比较复杂了,因为有两种僵尸,级别差距还大(冰车7、雪橇小队3),甚至经常出现下一波级别总和大于上一波的情况,前面那种表很难概括。
下表罗列了所有可能的情况,0表示冰车,1表示雪橇小队,数字顺序即出怪列表中的顺序:

这个并不需要一个个算,比如某波级别上限是13,先出一只(四只)雪橇小队,剩余容量10,那就找到前面上限为10的波次x,“1”后面加上x波的列表就是。不过w40还是太多了……
然后是僵尸个数:

这个应该也是可以算的,不过这次就放下了。

五、下期预告
下期可能会有:
权重为0、选卡界面展示、僵王、锤僵尸、PT抽搐、SetZombiesListPlus()、倒计时、雪人、墓碑/珊瑚/空降、无普僵关计算法、雪橇小队、固定出怪直接填满列表的统计、权重与概率……

(好吧其实我根本没打算做下去。)
最后感谢和风唐舞和blue-carambola的提醒,感谢uint8_t和Umbrella_leaf的帮助和纠错,感谢被我站在肩膀上的巨人们。