设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 1809|回复: 11
打印 上一主题 下一主题

[讨论] 为了解决RTAB的冲突,黑科技这次是真用足了(已熟肉)

[复制链接]

Lv5.捕梦者 (版主)

遠航の猫咪

梦石
3
星屑
22492
在线时间
2338 小时
注册时间
2005-10-15
帖子
1160

开拓者

跳转到指定楼层
1
发表于 2022-2-7 09:32:51 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 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

评分

参与人数 2+2 收起 理由
89444640 + 1 其实我看不懂XD
saterick + 1 精品文章

查看全部评分

SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。

Lv6.析梦学徒

老鹰

梦石
40
星屑
33434
在线时间
6555 小时
注册时间
2012-5-26
帖子
3178

极短24评委极短23参与极短22参与极短21评委老司机慢点开短篇十吟唱者组别冠军开拓者剧作品鉴家

2
发表于 2022-2-7 10:15:18 | 只看该作者
然而我觉得va默认不显示伤害数字,真的很不方便
可能也是因为伤害计算和显示是完全区分开的,导致了这一大堆的兼容扩展问题()

点评

VA的ActionResult看似啥效果都有 但是想要突破加东西 做起来并不比XP容易  发表于 2022-2-7 10:42
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
34877
在线时间
4148 小时
注册时间
2007-12-15
帖子
9983
3
发表于 2022-2-7 11:06:05 | 只看该作者
本帖最后由 89444640 于 2022-2-7 11:07 编辑

樱雅在土在我眼里是大神!我只记得他那个全动画XD,猫大就原谅我这里感慨几句吧。
虽然bug特别的多,但是毕竟能在0X年就实现了我想要的全动态战斗。
而且就效果来说,我还是挺满意的XD,因为无法联系都作者,bug我改不了就选择无视
我在本论坛也问很多次加强修改这个版本的,菜刀说,在我那个全动画最后的版本里,能看到不下5个人改造的痕迹,拿我的脚本比作是垃圾堆XD,
要不是他那个打死我不用RM做游戏,就因为他那个全动画我才会野路子练像素。
所以就这点来说,我非常感谢作者樱雅在土。

点评

不不不,gif哪有rm好玩?手动狗头  发表于 2022-2-8 18:46
嗯,我就是已经为有了横版才十几年如一日的画,不然就光做gif玩去了。这脚本作者冲这点就改名留史册,中国人好写历史嘛XD  发表于 2022-2-7 17:41
说夸张点,没有樱雅估计当年RM圈的玩家都要少一半。  发表于 2022-2-7 15:40
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
1
星屑
4954
在线时间
443 小时
注册时间
2006-1-31
帖子
1537
4
发表于 2022-2-7 15:37:08 | 只看该作者
膜拜猫大m(_ _)m
说到RTAB,我真的是很有很深情结与执念。老版本的vs几乎没有对“战斗系统”有过一点点研究,几乎就是靠RTAB那个纵版的缩放效果当遮羞布。和叶子、白菜两位大佬给vsp理战斗系统的时候,我当时是很执着的想要把RTAB作为基础弄成纵版,各种尝试、各种冲突之后无奈放弃,最终定型是基于异质型ATB+66的彩虹神剑插件整合的缝合系统。
猫大的成果放在这里,究竟还有没有机会再被使用到,想一想,真的也只能为猫大的情结点上一赞了。

点评

啊,打错字了,横版,囧  发表于 2022-2-8 11:31
RTAB默认就是纵版啊。。。  发表于 2022-2-8 10:42
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23963
在线时间
3338 小时
注册时间
2011-7-8
帖子
3925

开拓者

5
发表于 2022-2-7 19:23:35 | 只看该作者
好像没有处理Game_Damage.new(nil)的情况?总觉得在全动画里看到过self.damage = nil呢

点评

在Game_Battler里定义:def damage=(d); @damage=d ? Game_Damage.new(d) : nil; end  发表于 2022-2-7 20:30
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-8 18:05

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表