#============================================================================== # [ZTBS] -Zenith Tactical Battle System- タクティカルバトルシステム #  〜+B22:ちょっとAI強化〜      by 水夜 #  ver0.90  Zenith Creation (http://zenith.ifdef.jp/) #------------------------------------------------------------------------------ # マップ上での戦略的なバトルを実現。 #============================================================================== #============================================================================== # □ カスタマイズポイント #============================================================================== module ZTBSB21 # 敵が逃げ始めるHPの割合 ESCAPE_TEXT = "逃走開始" # end class Game_Enemy #-------------------------------------------------------------------------- # ● カスタマイズ #-------------------------------------------------------------------------- def go_point case self.id #============================================================================== # ↓↓設定箇所は説明の下にあります↓↓ #============================================================================== #------------------------------------------------------------------------------ # when エネミーID # return [X座標, Y座標] #------------------------------------------------------------------------------ # # ※指定したIDのイベントに設定されたバトラーと隣接すると # 「会話」コマンドが出て、指定したIDのコモンイベントが実行されます。 # #============================================================================== # ここより下が設定箇所です #============================================================================== when 31 return [7, 4] #============================================================================== # ここより上で設定してください #============================================================================== else return [0, 0] end end end class Scene_Map #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 2 : アクション判定) #-------------------------------------------------------------------------- def update_phase2_step2 @wait_count = ZTBS::ENEMY_THINKING # 行動できない場合 if @attacker.restriction == 4 # ステップを 10 に設定 $game_system.tactics_step = 10 return end # 移動頻度が 1 の場合 case @active_battler.move_frequency when 1 # 再移動可能距離を0にする @attacker.more_step = 0 # ステップを 5 に設定 $game_system.tactics_step = 5 return when 4 # 条件に適したバトラー取得 id = serect_battler($game_system.tactics_actors, :pinch_battler) @target_position = [$game_map.events[id].x, $game_map.events[id].y] else # 条件に適したバトラー取得 id = serect_battler($game_system.tactics_actors.keys) @target_position = [$game_map.events[id].x, $game_map.events[id].y] end # 移動エリア検索 search_route # 動けない場合 if @position.size == 1 # 何気にその場でいる @target_position = @position[0] else # 移動先決定 serect_position end # 移動エリアをセット set_movable_area(1) # ステップを 3 に設定 $game_system.tactics_step = 3 end #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 5 : アクション再判定) #-------------------------------------------------------------------------- def update_phase2_step5 @wait_count = ZTBS::ENEMY_THINKING # 一目散タイプの場合、その位置に行かない限り行動しない、でも防御だけはする if @active_battler.move_frequency == 5 # 再移動可能距離を0にする @attacker.more_step = 0 if Game_Battler.method_defined?("more_step") if [@active_battler.x, @active_battler.y] != @attacker.go_point # ステップを 10 に設定 $game_system.tactics_step = 10 end end # 防御 or 何もしない の場合 if @attacker.current_action.kind == 0 and (@attacker.current_action.basic == 1 or @attacker.current_action.basic == 3) # 再移動可能距離を0にする @attacker.more_step = 0 if Game_Battler.method_defined?("more_step") # ステップを 10 に設定 $game_system.tactics_step = 10 return # 逃げる(完全撤退) elsif @attacker.current_action.kind == 0 and @attacker.current_action.basic == 2 transform_to_object(@active_battler.id) end # 攻撃エリア検索 position = search_attack_area # 攻撃 の場合 if @attacker.current_action.kind == 0 and @attacker.current_action.basic == 0 # 攻撃範囲が定義されている場合 if defined? ENEMY_RANGE # 攻撃ターゲット判定 targets = check_attack_target(position) @fix_targets = targets if targets[1].size > 0 @targets = {} @target_position = targets[0] for i in targets[1] @targets[i] = $game_system.tactics_actors[i] end # 対象が全体でない場合 unless [2, 4, 6, 8].include?(@now_scope) # ターゲットが固定の場合、それを指定 if @fix_target == nil key = @targets.keys[rand(@targets.size)] else key = @fix_target end # ハッシュの中身を1つにする value = @targets[key] @targets.clear @targets[key] = value # 対象がランダムでない場合 if [1, 3, 5].include?(@now_scope) @fix_target = key else @fix_target = nil end end # 攻撃エリアをセット set_attack_area(1) # ステップを 6 に設定 $game_system.tactics_step = 6 return end else targets = battlers_in_area(position) @fix_targets = targets if targets.size > 0 @targets = {} id = decide_target(targets) @target_position = [$game_map.events[id].x, $game_map.events[id].y] if $game_system.tactics_actors.keys.include?(id) @targets[id] = $game_system.tactics_actors[id] else @targets[id] = $game_system.tactics_enemies[id] end # 攻撃エリアをセット set_attack_area(1) # ステップを 6 に設定 $game_system.tactics_step = 6 return end end # スキル の場合 elsif @attacker.current_action.kind == 1 # スキル取得 skill = $data_skills[@attacker.current_action.skill_id] # スキルターゲット判定 targets = check_skill_target(skill, position) @fix_targets = targets if targets[1].size > 0 @targets = {} @target_position = targets[0] for i in targets[1] if $game_system.tactics_actors.keys.include?(i) @targets[i] = $game_system.tactics_actors[i] else @targets[i] = $game_system.tactics_enemies[i] end end # 対象が全体でない場合 unless [2, 4, 6, 8].include?(@now_scope) # ターゲットが固定の場合、それを指定 if @fix_target == nil key = @targets.keys[rand(@targets.size)] else key = @fix_target end # ハッシュの中身を1つにする value = @targets[key] @targets.clear @targets[key] = value # 対象がランダムでない場合 if [1, 3, 5].include?(@now_scope) @fix_target = key else @fix_target = nil end end # 攻撃エリアをセット set_attack_area(1) # ステップを 6 に設定 $game_system.tactics_step = 6 return end end # ステップを 10 に設定 $game_system.tactics_step = 10 end #-------------------------------------------------------------------------- # ● 対象バトラー選択 #-------------------------------------------------------------------------- def serect_battler(targets, type = :nearest_battler) return method(type).call(targets) end #-------------------------------------------------------------------------- # ● 対象に最も近いポジション取得 #-------------------------------------------------------------------------- def nearest_position(target_pos, pos_list, max_step = 20) nr = nil for position in pos_list next_if = false # 判定を追加 for event in $game_map.point_events(position[0], position[1]) if event[1].character_name != "" and event[1] != @active_battler next_if = true break end end next if next_if r = (target_pos[0] - position[0]).abs + (target_pos[1] - position[1]).abs sa = (@active_battler.x - position[0]).abs + (@active_battler.y - position[1]).abs next if sa > max_step if nr == nil or r < nr nr = r nearest = position elsif r == nr srand if rand(2) == 0 nr = r nearest = position end end end return nearest end #-------------------------------------------------------------------------- # ● 対象から最も遠いポジション取得 #-------------------------------------------------------------------------- def far_away_position(target_pos, pos_list, max_step = 20) nr = nil for position in pos_list next_if = false # 判定を追加 for event in $game_map.point_events(position[0], position[1]) if event[1].character_name != "" and event[1] != @active_battler next_if = true break end end next if next_if r = (target_pos[0] - position[0]).abs + (target_pos[1] - position[1]).abs sa = (@active_battler.x - position[0]).abs + (@active_battler.y - position[1]).abs next if sa > max_step if nr == nil or r > nr nr = r far_away = position elsif r == nr srand if rand(2) == 0 nr = r far_away = position end end end return far_away end #-------------------------------------------------------------------------- # ● 残りHPの少ないバトラーを狙う #-------------------------------------------------------------------------- def pinch_battler(targets) result = nil for target in targets.values if result.nil? or (target.hp < result.hp) result = target end end return $game_system.tactics_actors.index(result) end #-------------------------------------------------------------------------- # ● 移動座標設定 #-------------------------------------------------------------------------- def serect_position sa = (@active_battler.x - @target_position[0]).abs + (@active_battler.y - @target_position[1]).abs move = @attacker.movable - 1 case @attacker.current_action.kind when 0 range = @attacker.attack_range[0][1] when 1 range = $data_skills[@attacker.current_action.skill_id].range[0][1] end escaping = XRXS.element_percent(@attacker_multy_element_set, ZTBSB21::ESCAPE_TEXT) # 移動頻度にて移動パターンを調整 case @active_battler.move_frequency when 1 # 動かない # 何気にその場でいる @target_position = @position[0] # 再移動可能距離を0にする @attacker.more_step = 0 if Game_Battler.method_defined?("more_step") when 2 # 待ち伏せ # 移動先決定 if (@attacker.hp * 100 / @attacker.maxhp) < escaping @target_position = far_away_position(@target_position, @position) elsif sa <= (move + range) @target_position = nearest_position(@target_position, @position, (sa - range)) else @target_position = @position[0] end when 3 # 間合い # 仕様上、避ける positions = [] for i in $game_system.tactics_actors.keys positions |= set_route($game_map.events[i]) end mikomi = @position - positions for i in $game_system.tactics_enemies.keys del = [$game_map.events[i].x, $game_map.events[i].y] mikomi.delete(del) end # 移動先決定 if (@attacker.hp * 100 / @attacker.maxhp) < escaping @target_position = far_away_position(@target_position, @position) elsif mikomi.empty? @target_position = far_away_position(@target_position, @position) else @target_position = nearest_position(@target_position, mikomi) end when 4 # 集中攻撃 if (@attacker.hp * 100 / @attacker.maxhp) < escaping @target_position = far_away_position(@target_position, @position) else @target_position = nearest_position(@target_position, @position) end when 5 # 一目散 position = @attacker.go_point if [@active_battler.x, @active_battler.y] == position # 何気にその場でいる @target_position = @position[0] # 再移動可能距離を0にする @attacker.more_step = 0 if Game_Battler.method_defined?("more_step") else # 辺りには目もくれない @target_position = nearest_position(position, @position) end when 6 # 突撃 if (@attacker.hp * 100 / @attacker.maxhp) < escaping @target_position = far_away_position(@target_position, @position) else @target_position = nearest_position(@target_position, @position) end end end #-------------------------------------------------------------------------- # ● 移動エリア & ルート検索 #-------------------------------------------------------------------------- def set_route(battler, movable = 0) if movable = 0 movable = $game_system.tactics_actors[battler.id].movable + 1 end max_step = movable result = [[battler.x, battler.y]] route = [[]] cost = [0] more_step = [0] for i in more_step x = result[i][0] y = result[i][1] # 下 if !result.include?([x, y + 1]) and (battler.passable?(x, y, 2) or @position[0] == [x, y + 1]) if Game_Map.method_defined?("move_cost") mikomi = cost[i] + $game_map.move_cost(battler, x, y + 1) if mikomi < movable result.push([x, y + 1]) route.push(route[i] + [2]) cost.push(mikomi) if cost.last < max_step more_step.push(route.index(route[i] + [2])) end end else result.push([x, y + 1]) route.push(route[i] + [2]) if route[i].size + 1 < max_step more_step.push(route.index(route[i] + [2])) end end end # 左 if !result.include?([x - 1, y]) and (battler.passable?(x, y, 4) or @position[0] == [x - 1, y]) if Game_Map.method_defined?("move_cost") mikomi = cost[i] + $game_map.move_cost(battler, x - 1, y) if mikomi < movable result.push([x - 1, y]) route.push(route[i] + [4]) cost.push(mikomi) if cost.last < max_step more_step.push(route.index(route[i] + [4])) end end else result.push([x - 1, y]) route.push(route[i] + [4]) if route[i].size + 1 < max_step more_step.push(route.index(route[i] + [4])) end end end # 右 if !result.include?([x + 1, y]) and (battler.passable?(x, y, 6) or @position[0] == [x + 1, y]) if Game_Map.method_defined?("move_cost") mikomi = cost[i] + $game_map.move_cost(battler, x + 1, y) if mikomi < movable result.push([x + 1, y]) route.push(route[i] + [6]) cost.push(mikomi) if cost.last < max_step more_step.push(route.index(route[i] + [6])) end end else result.push([x + 1, y]) route.push(route[i] + [6]) if route[i].size + 1 < max_step more_step.push(route.index(route[i] + [6])) end end end # 下 if !result.include?([x, y - 1]) and (battler.passable?(x, y, 8) or @position[0] == [x, y - 1]) if Game_Map.method_defined?("move_cost") mikomi = cost[i] + $game_map.move_cost(battler, x, y - 1) if mikomi < movable result.push([x, y - 1]) route.push(route[i] + [8]) cost.push(mikomi) if cost.last < max_step more_step.push(route.index(route[i] + [8])) end end else result.push([x, y - 1]) route.push(route[i] + [8]) if route[i].size + 1 < max_step more_step.push(route.index(route[i] + [8])) end end end end return result end end