- 积分
- 34677
- 威望
- 499
- 魅力
- 507
- 经验
- 20326
- 热心度
- 9
- 注册时间
- 2006-3-13
- 最后登录
- 2024-9-30
- 主题
- 134
- 回帖
- 4949
- 精华
- 35
- 阅读权限
- 150
TA的每日心情 | 郁闷 2015-6-6 16:12 |
---|
签到天数: 52 天 连续签到: 1 天 [LV.5]女巫
超级版主
- 积分
- 34677
|
关于UN:U命令产生BUG的研究
首先,这个BUG也许好早就有人发现.不过我是今天才认识到的,和大家分享一下研究心得.
事情起于对当年一幅WOG化出错地图的研究.
地图的名字是<Arena of death>,里面拥有很多宝箱和各种资源.当年玩时按照一般惯例不开启<替换物体>选项,但WOG化后仍然出错,由于当时不太懂ERM语法.但那句cannot find more objects 一直很深刻.出错后如果继续玩,后期会有意想不到的现象,比如特长兵种的,攻防都固定为400几以上了.
最近找到了那张地图重玩,问题依旧.此时已经比较容易找到出错的位置,是选项<一些箱子会有更多的钱>的问题,禁用了就没出错信息.
该选项对应的ERM是script00.erm中的以下语句:
- ** upgrade chests
- !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]检测选项是否开启
- !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
- !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
- !!DO679/1/v951/1&y3=1:P; [upgrade some of them]始循环所有宝箱,并使箱子有机会获得更多钱
- ** function to possibly upgrade a treasure chest
- !?FU679; [使箱子获得更多钱的函数]
- !!UN:U101/-1/-1/952; [get x/y/l of yellow square of chest into v952-v954]出错在此句上
- !!VRy1:S0 R99; [roll percentile dice]
- !!CH952&y1<8:B5; [8% chance for 2500 gold chest]
- !!CH952&y1>97:B6; [2% chance for 3000 gold chest]
- ** end of function
复制代码
乍看句子都很正常,为什么会出错呢?联想起cannot find more objects,估计是因为没有找到对应的物体(宝箱).
于是加入了在两段中加入几句来看看到底什么时候出错.
- !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]
- !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
- !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
- !!VRv9999:S0; [增加]
- !!IF:M^宝箱总数 %V951^; [增加]
- !!DO679/1/v951/1&y3=1:P; [upgrade some of them]
- ** function to possibly upgrade a treasure chest
- !?FU679;
- !!VRv9999:+1; [增加]
- !!UN:U101/-1/-1/952; [get x/y/l of yellow square of chest into v952-v954]
- !!VRy1:S0 R99; [roll percentile dice]
- !!CH952&y1<8:B5; [8% chance for 2500 gold chest]
- !!CH952&y1>97:B6; [2% chance for 3000 gold chest]
- ** end of function
复制代码 重新WOG化出错后,查看WOGERMLOG.TXT文件(记录变量信息文件).
发现V9999刚好循环到最后一个(V951)时出错.(V9999=V951)
再看看出错前一个宝箱的坐标v952-v954,翻看地图,俨然是最后一个的箱子了(地下层的最右下的该物体).
为了再验证是最后一个循环出错,减少了地图的宝箱,再试验一次,证实了此想法.
好吧,既然最后一次循环错误,直接原句循环次数减一就应该能解决问题.
使用!!VRv951:-1; 地图果真不再出错了.
(当然,后面DO循环也应该增加一句对v951变量的检测是否>0.沧版的例子就做得很细致了)
至此已经知道问题的关键.
为什么会刚好最后一个循环出错,而且真的已经没有找到箱子了?一定是程序算法漏算了.
我开始认为,是不是宝箱太多(该地图有900多个宝箱),所以出错.
于是删了又删,从900几个箱子删到500几,到300既但问题依旧.(停止试验)
又想,为啥其它地图又没有如此错误呢?
于是随机一个地图,又添加了很多箱子,奇怪的是,居然没有出现问题.
莫不是地图本身有问题吧?(开始神经了)
发呆了一阵子,突然头脑清醒起来,既然漏算了一个,那就该检测下程序漏了哪个坐标的箱子啊!真笨.
此时的第一个想法就是,很有可能是漏了第一个箱子.于是在加了句来检测有问题的地图.
!!IF&v9999=1:M^起始坐标 %V952-%V953-%V954^;
好了,果不其然,左上角的那个宝箱并不是第一个检测的箱子.(!!UN:U101/-1/-1/952;语法漏算了)
再检测没有问题的地图,最顶层最左的箱子却又可以检测得到!!!!
好了,终于知道问题的症结所在了.归纳如下:
!!UN:U101/-1/-1/952;类似的语法中(第三个参数-1代表是下一个),是获取一个物体的坐标的一种特殊方法.
但这方法有一个致命的BUG,当该类型的(这里101是箱子,后面的-1是任意)物体处于地面层最左上角时(0,0,0),
程序会直接漏掉,也就是说,语法是从(0,0,0)之后才开始检测的!
刚好昨天看到了沧版的一个很好的例子.正好用上了此类语法.
- ERM功能地图上生成的随机怪物初始化时数量增加,1级和2级增加4倍,3级至7级增加2倍,数量为1的怪物不增加,数量超过4000的怪物不增加
- ZVSE
- !?PI;
- !!FU199:P-199;
- !?FU199&x1=-199;
- !!UN:U54/-1/?y-1;
- !!VRv1:S-1;
- !!DO199/1/y-1/1&y-1>0:P199;
- !?FU199&x1=199;
- !!UN:U54/-1/-1/1; [留意这句]
- !!OBv1/v2/v3:U?v4;
- !!MA&v4>=0:Lv4/?y5;
- !!MO1:G?y6;
- !!FU&y6=1:E;
- !!VRy7:S0;
- !!VRy7&y5<=1:S4;
- !!VRy7&y5>=2:S2;
- !!VRy8:Sy6*y7;
- !!VRy8&y8>4000:S4000;
- !!MO1:Gy8;
复制代码 为了验证我的猜想,不妨试试在一个地图(0,0,0)的位置加入怪物,同时使用沧版的这段ERM.
这样就会在!!UN:U54/-1/-1/1; 这句上出错了.
由于有ERA的新版本,我第一时间查看了该段是否更新了.
原来已经被修正了,见下面的ERA代码(位于<78 wog - wogify.erm>文件中).- !!UN:P132/?y3; [check if Upgrading Treasure Chests option is enabled]
- !!UN&y3=1:U101/-1/?v951; [get number of treasure chests]
- !!VRv951:-1; reduce # of chests by 1 to fix bug (JHV)[减一是为了修正BUG]
- !!VRv952:S-1; [Initialize v952 to first object for faster UN:U format]
- !!DO679/1/v951/1&y3=1/v951>0:P; [upgrade some of them]
复制代码
值得一提的是,我个人认为直接减一不是唯一的修正方法.
事实上,UN:U获取物体坐标还有个方法,直接使用索引!
来看ERM帮助
----------------------------------------------------------------------------------------
U#1/#2/#3/#4;
获得一个物体的坐标
#1 = 物体的类型 (格式OB)
#2 = 物体的子类型(-1 = 任意)
#3 = 物体的索引 (1...N最后一个物体的索引)
#4 = 用于存储第一个坐标的v变量的索引
也就是说:v[#4]=x, v[#4+1]=y, v[#4+2]=l
举例:
U54/i/3/324; v324,v325, v326 现在存放类型54子类型i的第三个物体的坐标。
提示:
所有物体编号计算的顺序为:
从左到右,从上到下,从地面到地下。
----------------------------------------------------------------------------------------
既然我们已经使用循环了,那么循环的x16就可以担当索引的角色.
我觉得这句
!!UN:U101/-1/-1/952; [get x/y/l of yellow square of chest into v952-v954]
可改为
!!UN:U101/-1/x16/952;
注:后来发现这个虽然能影响第一个物体,但却严重影响到速度!使用索引的话,系统每次都要从头计算第N个位置的坐标,当地图物品较多时,就会异常缓慢!
所以直接将总数 -1 是最佳的方案!!另外,如果可以的话,地图的(0,0,0)位置最好不要放置有用的物体,以避免可能带来的问题.
好吧,测试是最好的验证.
不清楚大家是否都了解过这个BUG,故抛砖引玉一下.权当作个提醒.
[ 本帖最后由 贤知有您 于 2012-8-16 09:26 编辑 ] |
评分
-
2
查看全部评分
-
|