加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 SailCat 于 2017-12-16 03:58 编辑
原贴见此:https://rpg.blue/thread-376149-1-1.html
由于是旧站贴子,不再回复
以下补充两条:
1. 装备系统自动状态bug。
原RGSS1中装备防具会强制附加其自动状态,若卸除防具就会强制解除。
若防具A和防具B(不在同一位置)都指向同一个自动状态,先同时装备防具A和B,再卸除其中任何一个,自动状态就会消失。
修改方法:增加一个计数器,考量有多少装备指向了这个自动状态,只有全部卸除了才能解除。
可参考:https://rpg.blue/thread-404129-1-1.html
2. 技能公式的各种bug。
2.1 失明状态下物理技能恒missbug
原RGSS1的技能特效中,当技能的atk_f不为0时,其命中率要乘算使用者的命中率
使用者的命中率一般都是100,默认系统只有失明了才不是100
但因为一个失误,那个乘算公式写成了 hit *= user.hit / 100,导致等式右边的计算结果恒为零,即hit恒为零,即失明时物理技能恒miss
修改方法:Game Battler 3#120:hit = hit * user.hit / 100
2.2 淬攻击力的回复技能符号bug。
如果回复类技能受atk_f影响,攻击力会被减算,而不是加算
原因:原技能公式直接以power值加上atk_f的攻击力,当power小于0时,绝对值反而减小。
修改方法:Game Battler 3#128: power = skill.power + user.atk * skill.atk_f / (skill.power > 0 ? 100 : -100)
2.3 没有威力(但有atk_f)的伤害值恒为miss的bug
如果技能的威力设置为0,但因为有atk_f的影响,实际可以打出伤害值,表现为对象扣血但弹出伤害为miss
原因:判定将伤害覆写为Miss的条件中漏掉了对atk_f的判定
修改方法:Game Battler 3#187: if skill.power == 0 and skill.atk_f == 0
另外关于那个事件脚本返回nil或false的问题。经测试:
1) 返回nil并不会卡死啊……for循环(不带break)的返回就是nil,从不卡死
原解释器脚本:
# 返回值为 false 的情况下
if result == false
# 结束
return false
end很明显只有脚本返回值是false时才会返回false(卡死)
2)如果脚本在2行或以上,即使返回false也不会卡死
当且仅当脚本为1行,且返回值是false时,卡死
3)关于这个卡死是不是真的bug——这是一个feature,因为没处理好,成了bug
事件返回值是false还是true到有什么区别?
# 尝试执行事件列表、返回值为 false 的情况下 if execute_command == false return end # 推进索引 @index += 1
# 尝试执行事件列表、返回值为 false 的情况下
if execute_command == false
return
end
# 推进索引
@index += 1
这已经是解释器update代码的最后部分,如果执行事件指令的结果是false,将直接返回,否则,将索引推到下一个后,继续解析事件指令。
也就是说,事件返回true或者false,将决定索引是否下移。
如果下移,系统将不刷新,直接执行下条指令(除非执行了连续100条无刷新的指令,会强制刷新)
如果不下移,系统将刷新至少一帧,刷新完之后执行下条指令
指令默认不是一帧执行一条的,一帧可以执行很多条,大部分事件指令的解释器返回都是true
但有些指令,天生就是要阻塞后续执行,直到其执行完毕的
典型的比如显示文章——
不知道有没有试过用脚本显示文章(在RGSS1的变量代入没有“脚本”选项的年代,这个需求还挺经常遇到的)
如果在事件脚本中用$game_temp.message_text="xxx",会有两个问题
第一,这个对话框并不会立即显示,后面可能会继续执行很多其他指令,直到某个无法预知的时间点才显示
第二,这个对话框如果其后没有别的显示文章事件,用C键关不掉
第一个问题的解决办法,很简单的一条就是在那一句下面加上return false,阻塞事件继续向下执行,返回刷新,因此这实际上是设计成feature
理论上,在那一句后面加上return false也可以,但我试了的结果是卡死,因此这feature没做好,成了bug
原因在哪呢?
查看默认的解释器,有以下指令的返回值(可能)是false
显示文章(101)、显示选择项(102)、数值输入(103)、文章选项(104)(均为在文本框显示时)返回
输入键(105)、删除事件(116)、场所移动(201)、滚动(已在滚动时)(205)、准备渐变(221)、执行渐变(222)、战斗处理(301)、商店处理(302)、名称输入(303)、强制行动(立即行动)(339)、战斗中断(340)、调用各种画面(351-354)
全部察看之后可以发现,这些事件指令要么牵涉到场景的转换,要么牵涉到输入等待,要么不能同时执行两次。因此设置了false的返回值阻止继续执行后面的指令。
这其中,有很多事件,在command_xxx的最后执行过了@index +=1的操作,这样相当于解释器指针在执行完这些指令后,已经被移到了下一行,返回false不是为了跳过指针操作,是为了刷新
另外的一些事件,在command_xxx中返回false之前,并没有执行指针下移操作,这样相当于刷新一帧再回来的时候,解释器的指针还在这条事件指令上
这就可以解释为什么显示文章连续执行的时候不会乱,因为显示完第一条(返回true)后,到显示第二条时,$game_temp.message_text被设置过,直接就返回false,等你把对话框关了,回到解释器,指令还在这里
所有指令中,总是返回false,且指针不下移的只有两个,就是353(game over)和354(回title),原因也好理解。场景转换后的新场景连解释器都没有,自然剩下的指令都扔了,也无所谓指针了。
回到脚本:355(事件脚本)这个指令是个多行指令,要合并执行,它在执行完后返回之前的指针,默认是在"n-1"行这个位置。执行完以后,如果返回true,解释器就会默认下移一行,到了n行位置,这就是下一个事件了。
但如果返回的是false,画面刷新了以后解释器的位置在第n-1行。如果脚本有超过1行,这一行的指令代码是655。
655是不能执行的,系统会直接返回true并下移。这就是为什么2行以上的脚本即使返回false也不会卡,什么都不会发生(当然会多一次刷新)
惟一的问题在脚本只有一行的时候,刷完回来解释器发现这还是355的脚本指令,继续执行,false,返回,刷新回来,355,继续执行……卡死,而且由于反复执行Graphics.update并不会报错退出。
怎么解决这个问题,既保留返回false的刷新机制,又避免脚本卡死:
很简单:让脚本在返回false的时候把指针下移一行……
result = eval(script) # 返回值为 false 的情况下 if result == false # 推进索引 @index += 1 # 结束 return false end # 继续 return true
result = eval(script)
# 返回值为 false 的情况下
if result == false
# 推进索引
@index += 1
# 结束
return false
end
# 继续
return true
当然还有一个粗暴的办法,就是去掉这几行判定,让它永远返回true,不过那样的话,一旦需要执行类似公共事件随机遇敌(你要用脚本去改变parameters然后调用Scene_Battle)等需要刷新的效果时。为了避免执行出现问题,就需要在这段脚本之后插入一个1帧的等待指令。
让事件解释器停止解释返回刷新并不只能把返回值做成false,有很多刷新条件都可以。这其中,设置等待帧数,是最容易达成且没有副作用的一项。
至于脚本显示文章的第二个(C键关不掉)的问题:
需要增补以下两行脚本事件:
@message_waiting = true
$game_temp.message_proc = Proc.new {@message_waiting = false}
注意@message_waiting设为true将会和等待一样引发刷新,所以……不需要再返回false。
|