Project1

标题: 为了解决RTAB的冲突,黑科技这次是真用足了(已熟肉) [打印本页]

作者: SailCat    时间: 2022-2-7 09:32
标题: 为了解决RTAB的冲突,黑科技这次是真用足了(已熟肉)
本帖最后由 SailCat 于 2022-2-7 13:42 编辑

也不知道10几年前樱雅在土的RTAB是怎么在XP上整出来的,能和这么多年来几乎所有存世的战斗扩展脚本冲突(甚至和他自己的独立版战斗特效冲突),真的是醉了
最近在做这玩意的兼容性移植,其实很早就知道樱雅这个脚本的冲突来自伤害的处理,但是RTAB和战斗特效,都是修改伤害这一块的重头戏
但是全部跟完默认引擎之后,我发现,对于battle#damage=的处理,除了初始化是做的@damage=nil以外,所有的处理全部都是通过方法来完成,也就是damage是接口方法(虽然是accessor),不暴露的
针对它的写操作包括:
(伤害设置)self.damage = (包括+= -= *=),其实就是当它是个数值来处理
(伤害字符设置)self.damage ="Miss" 或者self.damage = ""
(无效伤害设置)self.damage = nil
针对它的读操作包括:
(伤害处理)self.hp -= self.damage
(伤害显示弹出)在内建的Sprite_Battler里会用到self.damage.to_s和self.damage.abs.to_s的操作
(动画处理)self.hp == "Miss"
XP和VA不太一样,XP的伤害是可以在战斗者上弹出来的,这个功能一直到MV才被恢复(谁叫VA根本就没有己方战斗者图形呢),所以才会有它既要运算,也要被当作字符串来处理的需要,不过RGSS1处理的也很巧妙,当它被设置成了字符串的时候,运算已经做完了,只剩最后一步了
甚至当它是数值的时候,只表示HP的伤害。SP都不表示(默认系统中使用纯SP回复药,伤害值居然是空的字符串你敢信)

而樱雅的RTAB脚本里面,damage是一个Hash,因为一个战斗者同时可能会有多个伤害
大多数战斗特效的脚本里面,damage也是一个Hash,因为伤害可能是个很复杂的机制(参考VA的Game_ActionResult,但是VA的ActionResult完全不能套用到XP,因为VA不用弹伤害啊)
Hash能abs,能+=, -=,还能和Miss去比较那可就有鬼了啊?

这时一个思路涌上脑海,既然是接口方法,那自然就可以封装,只要封装一个Game_Damage类,它
1)能像数值那样和别的数值进行四则运算,也可以自运算,还能支持abs操作
2)能被设置为某种字符串,并且原样返回以供显示,并且还能和字符串比较
3)能像Hash一样被独立key操作,操作出来的结果是原初的伤害,也就是可能为数值或者字符串,以便多重伤害显示
4)key要有意义,以便兼容战斗特效
那岂不是所有的问题都能解决了

说实在的在下手之前,在1.81的版本下,我都没信心能搞出来这么个东西
但最后还是搞出来了
以下熟肉
RUBY 代码复制
  1. #==============================================================================
  2. # ■ Game_Damage
  3. #------------------------------------------------------------------------------
  4. #  处理伤害的类,该类在 Game_Battler 的内部使用。
  5. #==============================================================================
  6. class Game_Damage < Hash
  7.   include Comparable
  8.   #--------------------------------------------------------------------------
  9.   # ● 初始化对像
  10.   #     args : 初始伤害值( HP / SP / 其他信息 )
  11.   #--------------------------------------------------------------------------
  12.   def initialize(*args)
  13.     return if args.empty?
  14.     case args[0]
  15.     when Numeric
  16.       self[:hp] = args[0]
  17.       args[1] && self[:sp] = args[1]
  18.       args[2] && self[:info] = args[2].to_s
  19.     when String
  20.       self[:info] = args[0]
  21.     when Hash
  22.       self.merge!(args[0])
  23.     when Array
  24.       initialize(*args[0])
  25.     end
  26.   end
  27.   #--------------------------------------------------------------------------
  28.   # ● 与数值运算的共轭处理
  29.   #     other : 被运算的另一个数值
  30.   #--------------------------------------------------------------------------
  31.   def coerce(other)
  32.     other.is_a?(Numeric) ? self.value.coerce(other) : [self.to_s, other.to_s]
  33.   end
  34.   #--------------------------------------------------------------------------
  35.   # ● 伤害数值
  36.   #--------------------------------------------------------------------------
  37.   def value
  38.     # 按照 HP / SP / 其他增加量 / 0 的顺序返回
  39.     self[:hp] || self[:sp] || self.values.detect {|x| x.is_a?(Numeric)} || 0
  40.   end
  41.   #--------------------------------------------------------------------------
  42.   # ● 植入 Numeric 类的方法
  43.   #--------------------------------------------------------------------------
  44.   def to_i;           value.to_i;         end
  45.   def abs;            value.abs;          end
  46.   def ceil;           value.ceil;         end
  47.   def floor;          value.floor;        end
  48.   def round;          value.round;        end
  49.   def truncate;       value.truncate;     end
  50.   def integer?;       value.integer?;     end
  51.   #--------------------------------------------------------------------------
  52.   # ● 转为字符串
  53.   #--------------------------------------------------------------------------
  54.   def to_s
  55.     empty? ? Vocab.miss : self[:info] || self.value.to_s
  56.   end
  57.   #--------------------------------------------------------------------------
  58.   # ● Miss 的判定
  59.   #--------------------------------------------------------------------------
  60.   def missed?
  61.     empty? or self[:info] == Vocab.miss
  62.   end
  63.   #--------------------------------------------------------------------------
  64.   # ● 大小比较判定
  65.   #--------------------------------------------------------------------------
  66.   def <=>(other)
  67.     # 不等号另一侧是数值的情况下
  68.     if other.is_a?(Numeric)
  69.       self.value <=> other
  70.     # 不等号另一侧是字符串的情况下
  71.     elsif other.is_a?(String)
  72.       self.to_s <=> other
  73.     # 不等号另一侧是伤害的情况下
  74.     elsif other.is_a?(Game_Damage)
  75.       # 如果两个伤害都为空
  76.       if self.empty? and other.empty?
  77.         0
  78.       # 如果自己的HP伤害有效
  79.       elsif self[:hp]
  80.         self[:hp] <=> (other[:hp] || 0)
  81.       # 如果另一个HP伤害有效
  82.       elsif @other[:hp]
  83.         0 <=> other[:hp]
  84.       end
  85.     end
  86.   end
  87.   #--------------------------------------------------------------------------
  88.   # ● 正号处理
  89.   #--------------------------------------------------------------------------
  90.   def +@
  91.     self.clone
  92.   end
  93.   #--------------------------------------------------------------------------
  94.   # ● 负号处理
  95.   #--------------------------------------------------------------------------
  96.   def -@
  97.     result = clone
  98.     result.each {|k, v| result[k] = -v if v.is_a?(Numeric)}
  99.     result
  100.   end
  101.   #--------------------------------------------------------------------------
  102.   # ● 四则运算处理
  103.   #--------------------------------------------------------------------------
  104.   def +(other);     calc(other, :+);            end
  105.   def -(other);     self + (-other);            end
  106.   def *(other);     calc(other, :*);            end
  107.   def /(other);     calc(other, :/);            end
  108.   def %(other);     calc(other, :%);            end
  109.   def **(other);    calc(other, :**);           end
  110.   #--------------------------------------------------------------------------
  111.   # ● 四则运算的计算(内部使用)
  112.   #--------------------------------------------------------------------------
  113.   private
  114.   def calc(other, sym)
  115.     # 与数值进行运算的情况下
  116.     if other.is_a?(Numeric)
  117.       result = clone
  118.       result.each {|k, v| result[k] = v.send(sym, other) if v.is_a?(Numeric)}
  119.       result
  120.     # 与另一个伤害进行运算的情况下
  121.     else
  122.       Game_Damage.new(merge(other) {|k, v1, v2| v1.send(sym, v2)})
  123.     end
  124.   end
  125. end


以下随便测试
RUBY 代码复制
  1. d = Game_Damage.new(72)
  2. p d + 15      # 89
  3. p d - 28      # 44
  4. p 13 + d      # 85
  5. p 22 - d      # -50
  6. p d * 2       # 144
  7. d *= -2
  8. p d.abs.to_s  # "144"
  9. p d.to_s      # "-144"
  10. d = Game_Damage.new("Miss")
  11. p d == "Miss" # true
  12. p d.to_s      # "Miss"
  13. p d.missed?    # true
  14. d[:info] = "HP UP!"
  15. d[:hp] = -14
  16. p d.missed?    # false
  17. p d.to_s      # "HP UP!"
  18. class Battler; attr_reader :hp; def hp=(hp); @hp=[hp, 200].min;end;end
  19. b = Battler.new
  20. b.hp = 20
  21. b.hp -= d
  22. p b.hp        # 34

测试结果:


测试中使用的d = Game_Damage.new(xx)的操作,实际上会在Battler内部封装为def damage=(d) @damage=Game_Damage.new(d) end


作者: 百里_飞柳    时间: 2022-2-7 10:15
然而我觉得va默认不显示伤害数字,真的很不方便
可能也是因为伤害计算和显示是完全区分开的,导致了这一大堆的兼容扩展问题()
作者: 89444640    时间: 2022-2-7 11:06
本帖最后由 89444640 于 2022-2-7 11:07 编辑

樱雅在土在我眼里是大神!我只记得他那个全动画XD,猫大就原谅我这里感慨几句吧。
虽然bug特别的多,但是毕竟能在0X年就实现了我想要的全动态战斗。
而且就效果来说,我还是挺满意的XD,因为无法联系都作者,bug我改不了就选择无视
我在本论坛也问很多次加强修改这个版本的,菜刀说,在我那个全动画最后的版本里,能看到不下5个人改造的痕迹,拿我的脚本比作是垃圾堆XD,
要不是他那个打死我不用RM做游戏,就因为他那个全动画我才会野路子练像素。
所以就这点来说,我非常感谢作者樱雅在土。
作者: saterick    时间: 2022-2-7 15:37
膜拜猫大m(_ _)m
说到RTAB,我真的是很有很深情结与执念。老版本的vs几乎没有对“战斗系统”有过一点点研究,几乎就是靠RTAB那个纵版的缩放效果当遮羞布。和叶子、白菜两位大佬给vsp理战斗系统的时候,我当时是很执着的想要把RTAB作为基础弄成纵版,各种尝试、各种冲突之后无奈放弃,最终定型是基于异质型ATB+66的彩虹神剑插件整合的缝合系统。
猫大的成果放在这里,究竟还有没有机会再被使用到,想一想,真的也只能为猫大的情结点上一赞了。
作者: guoxiaomi    时间: 2022-2-7 19:23
好像没有处理Game_Damage.new(nil)的情况?总觉得在全动画里看到过self.damage = nil呢




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1