目录
注:从本篇开始原注释不变,笔者写的注释标记改为两个##。
Game_Battler(分割定义二)代码解析
#==============================================================================
# ■ Game_Battler (分割定义 2)
#------------------------------------------------------------------------------
# 处理战斗者的类。这个类作为 Game_Actor 类与 Game_Enemy 类的
# 超级类来使用。
#==============================================================================
class Game_Battler
#--------------------------------------------------------------------------
# ● 检查状态
# state_id : 状态 ID
#--------------------------------------------------------------------------
def state?(state_id)
# 如果符合被附加的状态的条件就返回 ture
return @states.include?(state_id) ##Array.include?
end
#--------------------------------------------------------------------------
# ● 判断状态是否为 full
# state_id : 状态 ID
#--------------------------------------------------------------------------
def state_full?(state_id) ##判断状态是否已经施加过了
# 如果符合被附加的状态的条件就返回 false
unless self.state?(state_id) ##unless与if相反
return false ##没有这个状态(可以施加),就返回false
end
# 秩序回合数 -1 (自动状态) 然后返回 true ##应为“持续”
if @states_turn[state_id] == -1 ##这个状态不再持续了
return true
end
# 当持续回合数等于自然解除的最低回合数时返回 ture
return @states_turn[state_id] == $data_states[state_id].hold_turn
end ##目前我猜测这个方法用于判断本回合某状态是否被施加。
#--------------------------------------------------------------------------
# ● 附加状态
# state_id : 状态 ID
# force : 强制附加标志 (处理自动状态时使用)
#--------------------------------------------------------------------------
def add_state(state_id, force = false)
# 无效状态的情况下
if $data_states[state_id] == nil
# 过程结束
return
end
# 无法强制附加的情况下
unless force
# 已存在的状态循环
for i in @states
# 新的状态和已经存在的状态 (-) 同时包含的情况下、
# 本状态不包含变化为新状态的状态变化 (-)
# (ex : 战斗不能与附加中毒同时存在的场合)
if $data_states[i].minus_state_set.include?(state_id) and ##RPG::State.minu_state_set,描述此状态会解除的状态(也就是这个状态施加后会自动解除一些状态,比如战斗不能会解除其他所有状态)
not $data_states[state_id].minus_state_set.include?(i) ##如果已存在的状态(i)里有解除此状态的(state_id) 而且 这个状态不解除这个已存在的状态
# 过程结束
return ##直接返回,这个状态不附加了
end
end
end
# 无法附加本状态的情况下 ##感觉这个注释很奇怪
unless state?(state_id) ##加入状态的过程结束后并未返回,也就是可以叠加状态
# 状态 ID 追加到 @states 序列中
@states.push(state_id)
# 选项 [当作 HP 0 的状态] 有效的情况下
if $data_states[state_id].zero_hp
# HP 更改为 0
@hp = 0
end
# 所有状态的循环
for i in 1...$data_states.size
# 状态变化 (+) 处理
if $data_states[state_id].plus_state_set.include?(i)
add_state(i) ##处理本状态带来的附加状态
end
# 状态变化 (-) 处理
if $data_states[state_id].minus_state_set.include?(i)
remove_state(i) ##处理本状态带来的解除状态
end
end
# 按比例大的排序 (值相等的情况下按照强度排序)
@states.sort! do |a, b| #Array.sort! 返回其本身的排序
state_a = $data_states[a]
state_b = $data_states[b]
if state_a.rating > state_b.rating ##RPG::State.rating优先程度
-1 ##当a在b后返回-1,a在b前返回1,a等价于b返回0
elsif state_a.rating < state_b.rating
+1
elsif state_a.restriction > state_b.restriction ##PG::State.restriction 限制,理论上限制序号越高越优先
-1
elsif state_a.restriction < state_b.restriction
+1
else
a <=> b
end
end
end
# 强制附加的场合
if force
# 设置为自然解除的最低回数 -1 (无效)
@states_turn[state_id] = -1
end
# 不能强制附加的场合
unless @states_turn[state_id] == -1
# 设置为自然解除的最低回数
@states_turn[state_id] = $data_states[state_id].hold_turn
end
# 无法行动的场合
unless movable?
# 清除行动
@current_action.clear
end
# 检查 HP 及 SP 的最大值
@hp = [@hp, self.maxhp].min
@sp = [@sp, self.maxsp].min
end
#--------------------------------------------------------------------------
# ● 解除状态
# state_id : 状态 ID
# force : 强制解除标志 (处理自动状态时使用)
#--------------------------------------------------------------------------
def remove_state(state_id, force = false)
# 无法附加本状态的情况下
if state?(state_id)
# 被强制附加的状态、并不是强制解除的情况下
if @states_turn[state_id] == -1 and not force
# 过程结束
return
end
# 现在的 HP 为 0 当作选项 [当作 HP 0 的状态]有效的场合
if @hp == 0 and $data_states[state_id].zero_hp
# 判断是否有另外的 [当作 HP 0 的状态]状态
zero_hp = false
for i in @states
if i != state_id and $data_states[i].zero_hp
zero_hp = true
end ##如果另外有其他限制hp为0的状态,还是使得hp为0
end
# 如果可以解除战斗不能、将 HP 更改为 1
if zero_hp == false
@hp = 1
end
end
# 将状态 ID 从 @states 队列和 @states_turn hash 中删除
@states.delete(state_id)
@states_turn.delete(state_id)
end
# 检查 HP 及 SP 的最大值
@hp = [@hp, self.maxhp].min
@sp = [@sp, self.maxsp].min
end
#--------------------------------------------------------------------------
# ● 获取状态的动画 ID
#--------------------------------------------------------------------------
def state_animation_id
# 一个状态也没被附加的情况下
if @states.size == 0
return 0
end
# 返回概率最大的状态动画 ID
return $data_states[@states[0]].animation_id ##此时的@states应被排序过
end
#--------------------------------------------------------------------------
# ● 获取限制
#--------------------------------------------------------------------------
def restriction ##数据库状态里的限制条件,也就是不能行动等
restriction_max = 0 ##可以看出数据库里的限制条件只能同时出现一个,而其优先级递增
# 从当前附加的状态中获取最大的 restriction
for i in @states
if $data_states[i].restriction >= restriction_max
restriction_max = $data_states[i].restriction
end
end
return restriction_max
end
#--------------------------------------------------------------------------
# ● 判断状态 [无法获得 EXP]
#--------------------------------------------------------------------------
def cant_get_exp?
for i in @states
if $data_states[i].cant_get_exp
return true
end
end
return false
end
#--------------------------------------------------------------------------
# ● 判断状态 [无法回避攻击]
#--------------------------------------------------------------------------
def cant_evade?
for i in @states
if $data_states[i].cant_evade
return true
end
end
return false
end
#--------------------------------------------------------------------------
# ● 判断状态 [连续伤害]
#--------------------------------------------------------------------------
def slip_damage?
for i in @states
if $data_states[i].slip_damage
return true
end
end
return false
end
#--------------------------------------------------------------------------
# ● 解除战斗用状态 (战斗结束时调用)
#--------------------------------------------------------------------------
def remove_states_battle
for i in @states.clone ##用克隆是因为@states会被remove_state改变
if $data_states[i].battle_only
remove_state(i)
end
end
end
#--------------------------------------------------------------------------
# ● 状态自然解除 (回合改变时调用)
#--------------------------------------------------------------------------
def remove_states_auto
for i in @states_turn.keys.clone ##同上
if @states_turn[i] > 0
@states_turn[i] -= 1
elsif rand(100) < $data_states[i].auto_release_prob ##概率解除的情况
remove_state(i)
end
end
end
#--------------------------------------------------------------------------
# ● 状态攻击解除 (受到物理伤害时调用)
#--------------------------------------------------------------------------
def remove_states_shock
for i in @states.clone
if rand(100) < $data_states[i].shock_release_prob ##受到物理攻击的概率状态解除
remove_state(i)
end
end
end
#--------------------------------------------------------------------------
# ● 状态变化 (+) 的适用
# plus_state_set : 状态变化 (+)
#--------------------------------------------------------------------------
def states_plus(plus_state_set)
# 清除有效标志
effective = false
# 循环 (附加状态)
for i in plus_state_set
# 无法防御本状态的情况下
unless self.state_guard?(i) ##没找到这个方法的定义
# 这个状态如果不是 full 的话就设置有效标志
effective |= self.state_full?(i) == false ##如果状态未被施加就设effective为真,被施加就维持effective
# 状态为 [不能抵抗] 的情况下
if $data_states[i].nonresistance
# 设置状态变化标志
@state_changed = true ##不能抵抗是不能抵抗状态施加吗?
# 附加状态
add_state(i)
# 这个状态不是 full 的情况下
elsif self.state_full?(i) == false
# 将状态的有效度变换为概率、与随机数比较
if rand(100) < [0,100,80,60,40,20,0][self.state_ranks[i]] ##state_ranks为状态有效度
# 设置状态变化标志
@state_changed = true
# 附加状态
add_state(i)
end
end
end
end
# 过程结束
return effective
end
#--------------------------------------------------------------------------
# ● 状态变化 (-) 的使用
# minus_state_set : 状态变化 (-)
#--------------------------------------------------------------------------
def states_minus(minus_state_set)
# 清除有效标志
effective = false
# 循环 (解除状态)
for i in minus_state_set
# 如果这个状态被附加则设置有效标志
effective |= self.state?(i)
# 设置状态变化标志
@state_changed = true
# 解除状态
remove_state(i)
end
# 过程结束
return effective
end
end
state_guard?
我最开始并没有找到这个方法的定义。
首先这个方法于Game_Battler(分割定义二)的类方法state_plus中被self(也就是当前对象)调用。我注意到Game_Battler类本身是作为超级类书写的,因此可能会存在某些方法和属性被定义在它的派生类中的情况(可以分别定义,而这又不是接口类)。
所以我们首先要确定调用state_guard?的对象是什么。所以我们在此方法执行之前加上p self,让程序打印出当前对象,如图所示:
可以得出当前对象为Game_Actor的实例。在Game_Actor类中寻找,果然找到了这个方法的定义。
本方法用于确定角色穿戴的防具中对状态的防御,因为Game_Battler的两个派生类角色和敌人对本方法的处理完全不同(敌人直接返回false),所以其并未在Game_Battler中定义。
state_ranks同上。