植物大战僵尸吧 关注:341,552贴子:3,979,473

【LV5】从 Ch6的【PE】16炮 谈起

只看楼主收藏回复

Caution:本文少图不杀猫,单调的白底黑字可能很无聊。
Caution:本文正文对楼数要求严格,不同楼层间内容会以楼层数相互引用。请不要插楼打断正文,小心成为正文众矢之的。
附加文件一大堆,已打包,有附加文件和内含图(图见10L)两种模式。欢迎下载。本文也是附加文件之一,我会乱说?据说是遭遇茶楼后的原顺序保护,求证。

本文意在阐述测量某些有确定时间的行为的时间的测量、用按键精灵来完成种植物、发射玉米炮、唤醒冰蘑菇、自动存冰,并且给出【PVZ环境下等待直到确定时刻】问题的一种解法。


PE-ch6-16附加文档.rar
大小:15.01KB下载:34次转存:6次
文件已失效
回复
1楼2014-08-25 09:06
    留名。


    收起回复
    2楼2014-08-25 09:06


      回复
      3楼2014-08-25 09:07
        视频来自:优酷



        ===
        6A9EC0
        ├┬768
        │├—28 //自进入关卡以来的时间
        │├┬140 //红字对象属性
        ││├—88 //消失倒计时
        │├┬144 //卡槽,+28以前为整个卡槽的属性,以后为每格的属性,+50下一格
        ││├—70 //(Byte)为0时为冷却中(或被鼠标点中但未被种植),否则为可用
        │├—5568 /*时间戳*/
        │├—557C //已刷新波数(当前选卡)
        │├—559C //下一波僵尸刷新时间(倒计时)

        =表1 全文可能会用到的内存地址, 16进制, 用//注释的取自(*1), 用/* */注释的取自(*2)=


        回复
        4楼2014-08-25 09:07
          我们知道,含炮精确阵容的主要操作对象是玉米炮(废话)。玉米炮在设计时把y坐标锁定为行数。
          这样在手动操作时可以收3行的最主要僵尸,却漏了准星上一路(row)飞行的imp和pogo,和准星下一路刚召唤的伴舞。但行数没锁定准确就引来了上界之风。落点y坐标以函数关系准确偏移,虽然可以解决飞行imp和pogo问题(咦准星下一路的pogo问题没解决吧。。),但准星下一路甚至会漏掉冰车。(*3)(*4)
          x坐标没有锁定,这就给我们拦截imp之类需要精确x坐标的操作带来便利。
          我们使用炮的时候,往往注意的问题除了落点在哪行,通常是落点在哪列,而不是x坐标是多少。诚然我们可以背坐标公式(误)但很不方便。
          同时,落点x坐标为1~10的情况极其罕见。不是每个阵容都需要像DE20炮那样处理红字前跳跳。(*3)

          唔,扯远了。。开个玩笑。我们的点炮过程的参数可以决定炮的模糊或精确落点,把炮射到r行,横坐标或列数x。
          炮要点两次才能生效,要俩实数对;每次点炮都要决定一下炮位坐标,对于P及其衍生节奏来说还只是不简洁的问题。C及其衍生节奏。。非C非P变奏。。

          我们可以尝试着记录每个炮的CD或当前用到的是哪一个炮,作为内存读不到的全局变量。点哪个炮可以由该全局变量决定。
          炮在钱与阳光出没的场地里。点炮时比种植物更难防止点到钱。右键单击原点和左键单击要用的炮,轮流执行共10遍,减小点不到炮的概率。

          如果x<10,x的意思是列数。将它乘以80自动转换为x坐标。x可以是小数。为了照顾边路先进生红眼,DE神8的激活炸炸点就是8.6列。
          点击目标位置(x,85r+35)。更新下次要用的炮的序号。【85是针对PE和FE场景的。DE和NE场景应当为100,而RE和ME可能需要不简单的数据修正】

          思想十分简单,请同学们就以上所学知识写一枚点炮子程序。(笑


          回复
          7楼2014-08-25 09:09
            点炮相关全部整合在唯一的子程序中?那是不可能的。我们要发挥全局变量的力量。
            连3L大实验里都有提到初始化,这初始化得有多基础。。
            答4L问:PVZ变量和p1指针这种不断使用的东西,在初始化时定义好,有利于减少读数时的读内存次数,直接从p1开始读取第3级偏移。
            p1 = Plugin.Memory.Read32Bit(PVZ, Plugin.Memory.Read32Bit(PVZ, &H6a9ec0) + &H768)
            显然炮数、炮位这种固定的东西,调用再算浪费时间;炮号的本质是计数变量,也是要初始化的。
            我们的常量数组直接用array括在一起定义,多方便。。注意从第0项开始定义的。
            要用的炮的坐标就是(80pc(pnum),85pr(pnum)+35)。大多数程序语言的惯例是下标写作方括号,按键精灵这VB又不认了。。
            psum = 16 : pnum = 0
            pr = array(1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6)
            pc = array(5, 7, 5, 7, 1, 3, 5, 7, 1, 3, 5, 7, 5, 7, 5, 7)

            点冰则超简单。拿着咖啡豆往各个存冰位上都一点,冰号减个1不就完了么。。左键单击种不上又不会取消种植,不用管下次要用的冰号是什么。
            有抄袭,哦不,类比推理,的倾向。。冰号冰数也一起定义着。。
            isum = 2 : inum = 2
            ir = array(2, 1)
            ic = array(1, 1)

            我们知道,像这样定义的种植物点炮程序,执行时会取消掉正在进行的手工操作。
            手工存冰也太烦+略浪费CD。

            考虑自动存冰,自动存冰一旦成功,就要让冰号+1。这样,点冰程序可以改为:先尝试自动存原版冰,再只点场上第(冰号)个冰蘑菇。
            点冰时临时存原版冰,通常是为了应付“场上没有存冰,而准备启动预判冰前原版冰恰好CD完成”的情况,同时通过冰蘑菇的提前使用来保证后面出现的是“刚好CD完成”而非“刚好CD未完成”。2.95秒短么?
            自动存冰则需要考虑存冰位情况:是空闲的,还是正存贮着冰核弹坑,还是正被僵尸占领?同时,某些极限临时存冰,是要求最后一次预判冰,冰菇和咖啡要连着种的,这时原版冰和复制冰的区别就极为明显。我们有时需要指定哪种冰不能存,都能存时先存哪个。


            回复
            8楼2014-08-25 09:10
              为了交流方便,规定记号[x],表示读取指针x(别忘了指针也是数)所指内存的数值。
              为了执行时减少不必要读数,我们记下卡槽偏移 p = [[[0x6a9ec0]+0x768]+0x144]=[p1+0x144]。
              [p+0x70]表示第1个种子是否空闲。如果该种子正在装填,或正拿着准备种,还没种下去,则为0,否则为1,即使紫卡对应绿卡在场地中完全不存在,根本没法种(甚至拿不起来)。“种子”在(*1)中被写作“卡槽”,倒引起了歧义。。
              [p+0xC0]表示第2个种子是否空闲。注意,16进制下,7+5≠12。
              [p+0x110]表示第3个种子是否空闲。
              ……
              [p+0x50*k+0x20]表示第k个种子是否空闲。
              事实上,目前我们只需要这一列布尔值,不需要读取其他卡片相关,若核武2炮挂机要读CD判断形势,那又是另一回事了。所以在附加文档"PE-Ch6-16.Q"中,记下的是所谓“卡槽空闲(slot available)基本偏移”sa = [[[0x6a9ec0]+0x768]+0x144]+0x20 = [p1+0x144]+0x20,而直接用[sa + 0x50 * k]表示第k个卡片的空闲布尔量。

              显然这个过程是要被频繁且连续地调用的,为了保证存冰及时:这就导致调用该过程时,有很大概率是不能存冰,因为存冰位满了,或者冰菇卡忙着装填。存冰过程,附带了一个参数k,k=0时不种复制冰,k=1时不种普通冰。但经常得把k=2带进去,限制什么不能种的,那是少数。
              如果存冰位没有满,那么:如果复制冰卡空闲且k≠0,就种复制冰,否则(咦现在看起来好像又不是这个关系了,应该是并列的说)如果普通冰卡空闲且k≠1,就种普通冰。
              为了防止种的太快PVZ还没发现,新种的卡片的空闲布尔量来不及变化,那么。。
              复制冰空闲么?空闲。存冰。复制冰空闲么?空闲(PVZ程序还没来得及发现冰已经存过了,空闲布尔量保持为1)。存冰。存冰位满了。存冰位满了。存冰位满了。……
              这是反复调用存冰过程给一个 空闲着两个存冰位 的阵容存冰的执行细节。其实,还有1个空位;过程却以为,冰菇存满了。然后点预判冰。点到空位上明显失败,而脚本无法发现。
              所以我们种植某冰蘑菇后,不仅要inum=inum+1,还要延时(空语句就是延时了。。)直到PVZ发现那个冰种上了,空闲布尔量改为0为止。

              不过,这个自动存冰装置尚存在瑕疵,暂时适合只存冰的安全位。像那DE无南瓜6炮永久存冰位只有一个,另外3个分别是矿工占区、imp占区、冰车占区,还轮流占领,很少见几个临时冰位同时出现僵尸的;Ch5派生节奏的冰耗,单长期存冰位是撑不起的,第2个长期存冰的位置也只能依形势变化而改变:该装置并不适合这种情况。


              收起回复
              9楼2014-08-25 09:10
                事实上,存冰过程是要被频繁且连续地调用的,而在脚本运行时,绝大多数时间都在处理延时问题。这意味着,在延时程序中调用存冰程序会有比较好的效果。
                但我当时在编写脚本时认为,调用存冰过程需要耗费较大量的机时,会增大延时误差,就保留上述过程作为精确延时+lastf的维护。
                此外增加了一个粗略的纯延时roughdelay过程。同样需要参数t,和楼上那个t兼容,但对于t<0,dt>0不再维护lastf,而是认为已经延迟过了而立刻退出。

                尝试存储任意冰蘑菇,读取时间戳,计算相对时间dt:反复,直到dt-t>=0

                带存冰功能的粗略延时的算法就这么简单。我甚至都有贴源代码的冲动。
                偶尔会有先粗略延时到整十厘秒再精确延时到几厘秒,即连续调用这个roughdelay和楼上的timespot,的情形。

                如果将上面那行算法所读取内存值改成红字倒计时,则成为“一边尝试存冰一边读红字倒计时预判一边维护lastf”的过程。事实上这个过程没怎么调用,直接融合在第10波和第20波的预判里。这也是我8L把源代码中已经出现的“在timespot过程里用红字倒计时维护lastf”改成课后习题的原因。能存冰当然要抢timespot的生意,而timespot那部分就没有足够地调试。。


                按键精灵有一个奇葩bug:两个变量的加法易被看成字符串一样的连接。比如选卡界面读取countd=600,times=29714后,按公式lastf=times+countd计算时,结果会是29714600而不是30314。而按公式lastf=times-(-countd)结果是正常的。消歧义是经常看到在我的程序中有减去一个相反数的原因。


                回复
                11楼2014-08-25 09:23
                  事实上,在我的延时程序中,除了初始化过程和延迟到负数,lastf无法得到计算;inum和pnum也只是存取时使用的静态变量。如果简单地S/L而不保存lastf、pnum和inum这仨静态变量,而简单粗暴地goto调试点,则初始化体系会陷入混乱。为了得到有效S/L断点,有必要在脚本需调试语句前,模拟按下esc,在调试模式观察(watch)仨静态变量,调试阶段运行到esc生效时按Pause/Break键暂停脚本,记下它们的值,而在goto调试点前加入它们的赋值。然后改掉game1_13.dat的文件名,保存进度以得到新的game1_13.dat,设定为只读。

                  最后,通过调用之前制作的子程序实现轨道(如果单纯发布阵容的话我只会发这一小部分,也是本贴最简单的部分,1L和2L除外。)

                  阵图(学ND忘发阵图)

                  阵容到这里才出现,之前一直讲的是脚本制作,阵图出现在这里没错的说!
                  极限难度,阳光上升225。

                  2L视频使用的节奏为Ch6的标准变奏(*5)
                  循环节如下所示。
                  (时间的记录是采用Operation Time即操作轴,与一般意义上的ND轨道有所不同,所以看上去会很奇怪。单位仍为秒)
                  (炮从点击到落地时间3.73s,冰蘑菇从点咖啡豆到生效2.95s,请自行推算生效时刻。用OT更方便脚本制作)
                  wave 1(6s)
                  -1.43 - P - - P - MJ召唤伴舞前
                  -0.15 - D - - D - 撑杆进入可伤害区域后
                  wave 2(12s)
                  -2.45 - - - - - - I 利用确定的刷新时间,在读不到正确倒计时的状况下读时刻3.55s预判。
                  -0.73 - B - - B - 尽量保证不在热过渡时刷新
                  +6.27 - P - - P - 应当理解为何操作时刻为何只相当于变奏时间的一半(3.73s后炮生效,再过2s刷新。)


                  收起回复
                  12楼2014-08-25 09:25
                    参考资料:
                    (*1)tieba.baidu.com/p/2843347257 zjfaok,植吧,图片之下——PVZ程序内存中的数据地址列表(PC v1.0.0.1051限定
                    (*2)tieba.baidu.com/p/2567906948 testla,5p吧,【LV5】【EL】无尽挂机基础
                    (*3)tieba.baidu.com/p/2155500986 no_doudle,植吧,【我是礼物】【EL最多炮合集】来,射个痛快!
                    (*4)tieba.baidu.com/p/2647079397 FreezedIce,植吧,给男孩子的自X指南——冰冰教你撸炮
                    (*5)tieba.baidu.com/p/1059655283 风花镜月,植吧,【新节奏】神之绿卡魅力再现——无冰瓜之PE超前置16炮/DE15、14炮


                    回复
                    13楼2014-08-25 09:25
                      ende


                      2楼和3楼两个去死的茶楼,搞得正文【完·全】乱了


                      败毒的什么鬼畜广告判定系统。。9L(其实是11L)找了半天都找不到被判定为【广告】的东西在哪里。。。


                      沙发外销


                      回复
                      14楼2014-08-25 09:29
                        。。。


                        回复
                        来自Android客户端15楼2014-08-25 09:33
                          眼拙看不出会不会红先留名


                          收起回复
                          16楼2014-08-25 09:48
                            精前留


                            回复
                            来自Android客户端17楼2014-08-25 09:55


                              回复
                              来自Android客户端18楼2014-08-25 09:56
                                不明觉厉


                                回复
                                19楼2014-08-25 10:08
                                  前排


                                  回复
                                  22楼2014-08-25 11:23
                                    以前尝试过利用数组记录选卡组合,但或许是因为定义数组的位置存在问题,脚本运行速度很慢……应该和定义窗口名称常量一起定义么?


                                    收起回复
                                    来自iPhone客户端26楼2014-08-25 14:56
                                      = = 叫做“种子”恐怕还是会造成麻烦的歧义啊……


                                      回复
                                      来自手机贴吧27楼2014-08-25 15:09
                                        大触的世界我们不懂


                                        回复
                                        来自Android客户端28楼2014-08-25 17:41
                                          精后留名


                                          回复
                                          来自iPhone客户端29楼2014-08-25 17:50
                                            不明觉厉…


                                            回复
                                            来自Android客户端30楼2014-08-26 21:56
                                              留名


                                              回复
                                              来自Android客户端31楼2014-08-26 21:59
                                                令人感动的按键精灵进阶使用指南。
                                                不过别学我啊,我从来就没做过基层脚本的阵型实现。。。。
                                                楼主单独研究的能力已经点满 足够在超多炮上独当一面(其实早就可以了吧) 特颁发结业证书一张(图没有) 祝你能走的更远。


                                                收起回复
                                                来自手机贴吧32楼2014-08-26 23:05
                                                  测时间间隔还是CE下断点直接取更精确,每帧都能测到


                                                  回复
                                                  来自iPhone客户端33楼2014-08-26 23:15