#============================================================================== # ■ Game_Battler #------------------------------------------------------------------------------ #  思考ルーチン用にダメージ計算の部分だけを切り出す #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # ● 通常攻撃のダメージ計算(attack_effect より抜粋) # attacker : 攻撃者 (バトラー) #-------------------------------------------------------------------------- def attack_power(attacker) # 基本ダメージを計算 atk = [attacker.atk - self.pdef / 2, 0].max damage = atk * (20 + attacker.str) / 20 # 属性修正 damage *= elements_correct(attacker.element_set) damage /= 100 # ダメージの符号が正の場合 if damage > 0 # 防御修正 if self.guarding? damage /= 2 end end return damage end #-------------------------------------------------------------------------- # ● スキルの威力計算(skill_effect より抜粋) # user : スキルの使用者 (バトラー) # skill : スキル #-------------------------------------------------------------------------- def skill_power(user, skill) # 威力を計算 power = skill.power + user.atk * skill.atk_f / 100 if power > 0 power -= self.pdef * skill.pdef_f / 200 power -= self.mdef * skill.mdef_f / 200 power = [power, 0].max end # 倍率を計算 rate = 20 rate += (user.str * skill.str_f / 100) rate += (user.dex * skill.dex_f / 100) rate += (user.agi * skill.agi_f / 100) rate += (user.int * skill.int_f / 100) # 基本ダメージを計算 damage = power * rate / 20 # 属性修正 damage *= elements_correct(skill.element_set) damage /= 100 # ダメージの符号が正の場合 if damage > 0 # 防御修正 if self.guarding? damage /= 2 end end return damage end end #-------------------------------------------------------------------------- # ● 指定した場所に近づく # event : 移動させるユニット # : 目的地X座標 #-------------------------------------------------------------------------- def think_move_to_goal(event, goal_x, goal_y) # 目的地からの移動コスト計算 $game_map.move_algorythm.main(goal_x, goal_y, event.actor.move_power * 20, event) map_goal = $game_map.move_algorythm.move_point.clone # 今の場所から移動コスト計算 #map_action_save = Table.new($game_map.width,$game_map.height) $game_map.move_algorythm.main(event.x, event.y, event.actor.move_power, event) #map_action_save = $game_map.move_algorythm.move_action # 全ての場所から、目的地からの移動コスト+今の場所から移動コストが最小の場所を探す dist_min = 30000 for y in 0...$game_map.height for x in 0...$game_map.width dist = map_goal[x,y] << 8 # ユニットがあって、移動不可能なら無視 if $game_map.move_algorythm[x,y] & 1 != 0 && dist_min > dist if dist_min > dist dist_min = dist target_x = x target_y = y end end end end # 移動可能なら移動 if dist_min != 30000 $scene.move_event_to_goal(event, target_x, target_y) end end #-------------------------------------------------------------------------- # ● アクター用イテレータ (パーティ全体を考慮) # parameter : 1 以上なら ID、0 なら全体 #-------------------------------------------------------------------------- def iterate_party(group) # イベント全体分ループ for event in $game_map.events.values # ブロックを評価 yield event if (event.group & group) != 0 end end #-------------------------------------------------------------------------- # ● アクター用イテレータ (パーティ全体を考慮) # parameter : 1 以上なら ID、0 なら全体 #-------------------------------------------------------------------------- def iterate_enemy(group) # イベント全体分ループ for event in $game_map.events.values # ブロックを評価 yield event if (event.group & group) != 0# && event.actor.state?(16) == false end end #-------------------------------------------------------------------------- # ● 一番近い敵に近づく # event : 移動させるユニット #-------------------------------------------------------------------------- def Think_MoveToNearUnit(unit) $game_map.move_algorythm.main(unit.x, unit.y, unit.actor.move_power, unit) dist_min = 30000 eventTarget = nil # 一番近い敵を捜す iterate_enemy(1) do |event| dist = distance(unit.x, unit.y, event.x, event.y) if dist_min > dist dist_min = dist eventTarget = event end end # 一番近い敵がみつかったら、それに近づくよう移動 if dist_min != 30000 think_move_to_goal(unit, eventTarget.x, eventTarget.y) end end class ThinkStruct attr_accessor :nPowerMax # 評価値 attr_accessor :target_x # 移動X座標 attr_accessor :target_y # 移動Y座標 attr_accessor :skill_id # 使用スキル attr_accessor :nTargetUnit # 攻撃対象 end #-------------------------------------------------------------------------- # ● 一番近い敵を捜す #-------------------------------------------------------------------------- def search_near_enemy(unit) unit_near = nil dist_min = 30000 iterate_enemy(1) do |event| dist = distance(unit.x, unit.y, event.x, event.y) if dist_min > dist dist_min = dist unit_near = event end end return unit_near end #-------------------------------------------------------------------------- # ● 攻撃可能、または回復可能範囲を計算 #-------------------------------------------------------------------------- def set_max_range(unit) unit.max_range = unit.actor.range unit.heal_range = 0 for i in 0...unit.actor.skills.size skill = $data_skills[unit.actor.skills[i]] if skill != nil # SP 切れなどで使用できなくなった場合を確認 if unit.actor.skill_can_use?(skill.id) # 回復用スキル if (skill.scope == 3 or skill.scope == 5) && unit.heal_range < skill.range unit.heal_range = skill.range # 攻撃用スキル elsif skill.scope == 1 && unit.max_range < skill.range unit.max_range = skill.range end end end end end #-------------------------------------------------------------------------- # ● 一番近い敵に攻撃しつつ逃げる #-------------------------------------------------------------------------- def think_hitandaway(unit) # 攻撃可能、または回復可能範囲を計算 set_max_range(unit) # 一番近い敵を捜す unit_near = search_near_enemy(unit) if unit_near == nil return nil end dist_min = distance(unit.x, unit.y, unit_near.x, unit_near.y) if dist_min <= unit.actor.move_power + unit.max_range || unit.heal_range != 0 pTS = ThinkStruct.new pTS.nPowerMax = -30000 # 一番近い敵の移動コスト計算 map_near = Table.new($game_map.width,$game_map.height) $game_map.move_algorythm.main(unit_near.x, unit_near.y, unit_near.actor.move_power * 10, unit_near, false) map_near = $game_map.move_algorythm.move_point.clone # 指定ユニットの移動コスト計算 move_power = 0 if unit.move_type != 0 move_power = unit.actor.move_power end $game_map.move_algorythm.main(unit.x, unit.y, move_power, unit) rangeMin = 1 rangeMax = unit.actor.range # 全ての場所を検索 for y in 0...$game_map.height for x in 0...$game_map.width # 移動可能なら if $game_map.move_algorythm.move_action[x,y] & 1 != 0 # 全敵ユニット検索 iterate_enemy(1) do |event| # 射程内なら dist = distance(x, y, event.x, event.y) if dist <= rangeMax && dist >= rangeMin # 一番大きいダメージが出るユニットに攻撃 nPower = event.actor.attack_power(unit.actor) # 集中攻撃しないよう、距離も考慮する nPower += 10000 - $game_map.move_algorythm.move_point[x,y] * 16 if pTS.nPowerMax < nPower pTS.skill_id = 0 pTS.nPowerMax = nPower pTS.nTargetUnit = event.id pTS.target_x = x pTS.target_y = y end end end # 全スキル検索 for i in 0...unit.actor.skills.size skill = $data_skills[unit.actor.skills[i]] # 使用可能なら if skill != nil && unit.actor.skill_can_use?(skill.id) # 回復用 if (skill.scope == 3 or skill.scope == 5) # 全味方ユニット検索 iterate_party(2) do |event| dist = distance(x, y, event.x, event.y) # 射程内なら if dist <= skill.range # 最大HPと今HPの差が大きいユニットに回復 nPower = event.actor.maxhp - event.actor.hp if nPower != 0 nPower += map_near[x,y] * 256 if pTS.nPowerMax < nPower pTS.skill_id = unit.actor.skills[i] pTS.nPowerMax = nPower pTS.nTargetUnit = event.id pTS.target_x = x pTS.target_y = y end end end end # 攻撃用 elsif skill.scope == 1 # 全敵ユニット検索 iterate_enemy(1) do |event| dist = distance(x, y, event.x, event.y) # 射程内なら if dist <= skill.range # 一番大きいダメージが出るユニットに攻撃 # nPower = event.actor.skill_power(unit.actor, skill) # 一番近いユニットから遠く離れられる場所から攻撃 nPower = map_near[x,y] * 256 # 集中攻撃しないよう、距離も考慮する nPower += 10000 - $game_map.move_algorythm.move_point[x,y] * 16 if pTS.nPowerMax < nPower pTS.skill_id = unit.actor.skills[i] pTS.nPowerMax = nPower pTS.nTargetUnit = event.id pTS.target_x = x pTS.target_y = y end end end end end end end end end # 攻撃可能なら if pTS.nPowerMax != -30000 # 指定位置まで移動 $scene.move_event_to_goal(unit, pTS.target_x, pTS.target_y) return pTS end return nil end end #-------------------------------------------------------------------------- # ● 思考ルーチン #-------------------------------------------------------------------------- def Think(group) for event in $game_map.events.values if event.group & group != 0 && event.wait_time <= 0 pTS = think_hitandaway(event) if pTS != nil $scene.sim_battle(event.id, pTS.nTargetUnit, pTS.skill_id) event.action_end #interpreter = Interpreter.new #interpreter.setup(event.list, event.id) # インタプリタを更新 #interpreter.update return false end end end for event in $game_map.events.values if event.group & group != 0 && event.wait_time <= 0 case event.move_type #when 0 #if $game_map.think_flag == 0 #event.action_end #event.wait_time = 100 #event.step_anime = false #else # Think_MoveToNearUnit(event) #end when 2 Think_MoveToNearUnit(event) when 3..4 if event.think_type == 3 event.think_type = 4 think_move_to_goal(event, event.think_param1, event.think_param2) else event.think_type = 3 think_move_to_goal(event, event.think_param3, event.think_param4) end end event.action_end return false end end return true end