#============================================================================== # [ZTBS] -Zenith Tactical Battle System- タクティカルバトルシステム #  〜+B9:ZTBS ScopeEx併用化〜   by 水夜 #  ver0.90  Zenith Creation (http://zenith.ifdef.jp/) #------------------------------------------------------------------------------ # マップ上での戦略的なバトルを実現。 #  ※「CP制御ターンシステム」・・・スクリプトシェルフ(桜雅在土氏) #                   http://scriptshelf.jpn.org/x/ #============================================================================== module ZTBS MOVEABLE_SA = [0, 0.5, 1, 1.5, 2.5] # 移動し始める距離(移動距離への倍率) end #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map #-------------------------------------------------------------------------- # ● 発動可能判定 #-------------------------------------------------------------------------- def possible_action? # 範囲内にカーソルがあるか判定 if !in_area?($game_player.x, $game_player.y) return false end # 効果範囲内に対象がいるか判定 case @attacker.current_action.kind when 0 if @attacker.current_action.basic < 4 # 効果範囲を確認 if Game_Battler.method_defined?("multy_element_set") @attacker.set_xrxs69_special_scope(@attacker.multy_element_set) elsif @attacker.set_xrxs69_special_scope(@attacker.equip_element_set) end case @attacker.current_action.scope_force when 12 scope = 2 when 0 scope = 1 else scope = @attacker.current_action.scope_force end if defined? @attacker.attack_range and @attacker.attack_range != nil battler_exist = @attacker.attack_range[1][3] else battler_exist = true end # 効果範囲で分岐 case scope when 0 return false when 1, 2, 9 @can_attack = target_in_area($game_system.tactics_enemies.keys) when 3, 4, 10 @can_attack = target_in_area($game_system.tactics_actors.keys) when 5, 6 return true when 8, 11 @can_attack = target_in_area($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) end @now_scope = scope if @attacker.current_action.self_inclusion and not @can_attack.include?(@active_battler.id) @can_attack += target_in_area([@active_battler.id]) end if @attacker.current_action.self_exclusion and @can_attack.include?(@active_battler.id) @can_attack.delete(@active_battler.id) end else @can_attack = [] $game_map.point_events($game_player.x, $game_player.y).each{|p| @can_attack.push(p[1].id) } return can_command?($game_player.x, $game_player.y, @comvalue) end when 1 skill = $data_skills[@attacker.current_action.skill_id] battler_exist = skill.range[1][3] # 効果範囲を確認 @attacker.set_xrxs69_special_scope(@attacker.skill_element_set(skill)) case @attacker.current_action.scope_force when 12 if [1, 3, 5].include?(skill.scope) scope = skill.scope + 1 else scope = skill.scope end when 0 scope = skill.scope else scope = @attacker.current_action.scope_force end case scope when 0 return false when 1, 2, 9 @can_attack = target_in_area($game_system.tactics_enemies.keys) when 3, 4, 10 @can_attack = target_in_area($game_system.tactics_actors.keys) when 5, 6 return true when 8, 11 @can_attack = target_in_area($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) end @now_scope = scope if @attacker.current_action.self_inclusion and not @can_attack.include?(@active_battler.id) @can_attack += target_in_area([@active_battler.id]) end if @attacker.current_action.self_exclusion and @can_attack.include?(@active_battler.id) @can_attack.delete(@active_battler.id) end when 2 item = $data_items[@attacker.current_action.item_id] battler_exist = item.range[1][3] # 効果範囲を確認 @attacker.set_xrxs69_special_scope(item.element_set) case @attacker.current_action.scope_force when 12 if [1, 3, 5].include?(item.scope) scope = item.scope + 1 else scope = item.scope end when 0 scope = item.scope else scope = @attacker.current_action.scope_force end case scope when 0 return false when 1, 2, 9 @can_attack = target_in_area($game_system.tactics_enemies.keys) when 3, 4, 10 @can_attack = target_in_area($game_system.tactics_actors.keys) when 5, 6 return true when 8, 11 @can_attack = target_in_area($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) end @now_scope = scope if @attacker.current_action.self_inclusion and not @can_attack.include?(@active_battler.id) @can_attack += target_in_area([@active_battler.id]) end if @attacker.current_action.self_exclusion and @can_attack.include?(@active_battler.id) @can_attack.delete(@active_battler.id) end end if @can_attack.size == 0 @can_attack = nil return false end # カーソル位置に対象がいるか判定 if battler_exist and @battler == nil return false end return true end #-------------------------------------------------------------------------- # ● 攻撃ターゲット判定 (エネミー用) #-------------------------------------------------------------------------- def check_attack_target(position_list) # 効果範囲を確認 if Game_Battler.method_defined?("multy_element_set") @attacker.set_xrxs69_special_scope(@attacker.multy_element_set) elsif @attacker.set_xrxs69_special_scope(@attacker.equip_element_set) end case @attacker.current_action.scope_force when 12 scope = 2 when 0 scope = 1 else scope = @attacker.current_action.scope_force end battlers = [] # 対象の種類取得 case scope when 1, 2, 9 n = $game_system.tactics_actors.keys type = 0 for i in n battlers.push($game_map.events[i]) end when 3, 4, 7, 10 n = $game_system.tactics_enemies.keys type = 1 for i in n battlers.push($game_map.events[i]) end when 8, 11 n = $game_system.tactics_actors.keys type = 2 for i in n battlers.push($game_map.events[i]) end end @now_scope = scope if @attacker.attack_range[1][3] on_target = true else on_target = false end # 対象エリア検索 target_battlers = [[], [], false] for position in position_list d = turn_enemy(position) next_position = 0 for target in battlers if (target.x != position[0] or target.y != position[1]) and on_target next_position += 1 end end if next_position == battlers.size next end target_positions = search_target_area(position[0], position[1], d) battler_count = [] for area in target_positions for target in battlers if target.x == area[0] and target.y == area[1] battler_count.push(target.id) end end # まず、対象が多いところを優先 if battler_count.size > target_battlers[1].size target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = on_area?(position[0], position[1], type) # 次に、カーソル位置にバトラーがいるところを優先 elsif battler_count.size == target_battlers[1].size if on_area?(position[0], position[1], type) if target_battlers[2] if rand(2) == 0 target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = true end else target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = true end end end end end d = turn_enemy(target_battlers[0]) if @active_battler.direction != d @active_battler.turn(d) end return target_battlers end #-------------------------------------------------------------------------- # ● スキルターゲット判定 (エネミー用) #-------------------------------------------------------------------------- def check_skill_target(skill, position_list) battlers = [] # 効果範囲を確認 @attacker.set_xrxs69_special_scope(@attacker.skill_element_set(skill)) case @attacker.current_action.scope_force when 12 if [1, 3, 5].include?(skill.scope) scope = skill.scope + 1 else scope = skill.scope end when 0 scope = skill.scope else scope = @attacker.current_action.scope_force end # 対象の種類取得 case scope when 1, 2, 9 n = $game_system.tactics_actors.keys type = 0 for i in n battlers.push($game_map.events[i]) end when 3, 4, 7, 10 n = $game_system.tactics_enemies.keys type = 1 for i in n battlers.push($game_map.events[i]) end when 8, 11 n = $game_system.tactics_actors.keys type = 2 for i in n battlers.push($game_map.events[i]) end end @now_scope = scope if skill.range[1][3] on_target = true else on_target = false end # 対象エリア検索 target_battlers = [[], [], false] for position in position_list d = turn_enemy(position) next_position = 0 for target in battlers if (target.x != position[0] or target.y != position[1]) and on_target next_position += 1 end end if next_position == battlers.size next end target_positions = search_target_area(position[0], position[1], d) battler_count = [] for area in target_positions for target in battlers if target.x == area[0] and target.y == area[1] battler_count.push(target.id) end end # まず、対象が多いところを優先 if battler_count.size > target_battlers[1].size target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = on_area?(position[0], position[1], type) # 次に、カーソル位置にバトラーがいるところを優先 elsif battler_count.size == target_battlers[1].size if on_area?(position[0], position[1], type) if target_battlers[2] if rand(2) == 0 target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = true end else target_battlers[0] = position target_battlers[1] = battler_count target_battlers[2] = true end end end end end d = turn_enemy(target_battlers[0]) if @active_battler.direction != d @active_battler.turn(d) end return target_battlers end #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ ステップ 6 : 対象選択) #-------------------------------------------------------------------------- def update_phase1_step6 # カーソル位置のバトラー(イベント)取得 get_cursor_battler # ヘルプウィンドウにアクター or エネミーをセット set_battler_info # 座標から向きを変える sx = $game_player.x - @active_battler.x sy = $game_player.y - @active_battler.y # 横の距離のほうが長い場合 if sx.abs > sy.abs # 左右方向で指定イベントのいるほうを向く result = sx > 0 ? 6 : 4 # 縦の距離のほうが長い場合 elsif sx.abs < sy.abs # 上下方向で指定イベントのいるほうを向く result = sy > 0 ? 2 : 8 # 同じ場合 else # 右下 if sx > 0 and sy > 0 if @active_battler.direction == 4 or @active_battler.direction == 8 result = 6 else result = @active_battler.direction end # 右上 elsif sx > 0 if @active_battler.direction == 2 or @active_battler.direction == 4 result = 6 else result = @active_battler.direction end # 左下 elsif sy > 0 if @active_battler.direction == 6 or @active_battler.direction == 8 result = 4 else result = @active_battler.direction end # 左上 elsif sx < 0 and sy < 0 if @active_battler.direction == 2 or @active_battler.direction == 6 result = 4 else result = @active_battler.direction end # 中心 else result = @active_battler.direction end end if @active_battler.direction != result @active_battler.turn(result) @battler = @active_battler set_attack_area(0) end # C ボタンが押された場合 if Input.trigger?(Input::C) and !Game.player.moving? # 発動可能な場合 if possible_action? @back_step2 = nil # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # カーソルを固定 $game_player.not_update = true # エリアを解放 dispose_area # ステップ 7 へ移行 $game_system.tactics_step = 7 @select = nil if @revival == nil # ターゲットを取得 @targets = {} for i in @can_attack if $game_system.tactics_actors.keys.include?(i) @targets[i] = $game_system.tactics_actors[i] $game_map.events[i].turn_toward_event(@active_battler.id) end if $game_system.tactics_enemies.keys.include?(i) @targets[i] = $game_system.tactics_enemies[i] $game_map.events[i].turn_toward_event(@active_battler.id) end end # 対象が全体でない場合 unless [2, 4, 6, 8].include?(@now_scope) if @fix_target != nil key = @fix_target else key = @targets.keys[rand(@tatgets.size)] end # ハッシュの中身を1つにする value = @targets[key] @targets.clear @targets[key] = value if [1, 3, 5].include?(@now_scope) @fix_target = key end end # 戦闘不能回復の場合 else $game_map.events[@targets.keys[0]].moveto($game_player.x, $game_player.y) @active_battler.turn_toward_position($game_player.x, $game_player.y) $game_map.events[@targets.keys[0]].turn_toward_event(@active_battler.id) end @revival = nil @can_attack = nil # アクション結果作成 case @attacker.current_action.kind when 0 if @attacker.current_action.basic < 4 make_basic_action_result else event_id = cando_id($game_player.x, $game_player.y) common_id = @talk_events[event_id][1] $game_system.map_interpreter.setup($data_common_events[common_id].list, 0) @talk_events.delete(event_id) # ステップ 10 へ移行 $game_system.tactics_step = 10 end when 1 make_skill_action_result when 2 make_item_action_result end else # ブザー SE を演奏 $game_system.se_play($data_system.buzzer_se) end end # B ボタンが押された場合 if Input.trigger?(Input::B) and !Game.player.moving? @targets = nil @revival = nil # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # エリアを解放 dispose_area # カーソル位置を戻す back_cursor # カーソルを固定 $game_player.not_update = true if @back_step2 != nil and @back_step2 # ステップ 2 へ移行 $game_system.tactics_step = 2 if @select != nil case @attacker.current_action.kind when 1 # セレクトウィンドウを作成 make_select_window(1, @attacker, @skill) @select = 2 when 2 # セレクトウィンドウを作成 make_select_window(2, nil, @item) @select = 3 end else @back_step2 = nil # コマンドウィンドウを作成 make_command_window(1) end else # ステップ 5 へ移行 $game_system.tactics_step = 5 if @select != nil case @attacker.current_action.kind when 1 # セレクトウィンドウを作成 make_select_window(1, @attacker, @skill) @select = 1 when 2 # セレクトウィンドウを作成 make_select_window(2, nil, @item) @select = 2 end else # コマンドウィンドウを作成 make_command_window end end end end #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 2 : アクション判定) #-------------------------------------------------------------------------- def update_phase2_step2 @wait_count = ZTBS::ENEMY_THINKING # 行動できない場合 if @attacker.restriction == 4 # ステップを 10 に設定 $game_system.tactics_step = 10 return end # 防御 or 何もしない の場合 if @attacker.current_action.kind == 0 and (@attacker.current_action.basic == 1 or @attacker.current_action.basic == 3) # ステップを 10 に設定 $game_system.tactics_step = 10 return end # 攻撃エリア検索 position = search_attack_area # 攻撃 の場合 if @attacker.current_action.kind == 0 and @attacker.current_action.basic == 0 and @active_battler.move_frequency != 6 # 攻撃範囲が定義されている場合 if defined? ENEMY_RANGE # 攻撃ターゲット判定 targets = check_attack_target(position) @fix_targets = targets if targets[1].size > 0 @targets = {} @total_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 else # 最も近いバトラー取得 case @now_scope when 0, 1, 2, 5, 6, 9 id = nearest_battler($game_system.tactics_actors.keys) when 3, 4, 7, 10 id = nearest_battler($game_system.tactics_enemies.keys) when 8, 11 id = nearest_battler($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) end @target_position = [$game_map.events[id].x, $game_map.events[id].y] end else @attacker.set_xrxs69_special_scope(@attacker.skill_element_set(skill)) case @attacker.current_action.scope_force when 12 if [1, 3, 5].include?(skill.scope) scope = skill.scope + 1 else scope = skill.scope end when 0 scope = skill.scope else scope = @attacker.current_action.scope_force end @now_scope = scope # 対象の種類取得 case scope when 1, 2, 9 type = 0 when 3, 4, 7, 10 type = 1 when 8, 11 type = 2 end targets = battlers_in_area(position, type) @fix_targets = targets if targets.size > 0 @targets = {} @total_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 else # 最も近いバトラー取得 case @now_scope when 0, 1, 2, 5, 6, 9 id = nearest_battler($game_system.tactics_actors.keys) when 3, 4, 7, 10 id = nearest_battler($game_system.tactics_enemies.keys) when 8, 11 id = nearest_battler($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) end @target_position = [$game_map.events[id].x, $game_map.events[id].y] end end # スキル の場合 elsif @attacker.current_action.kind == 1 and @active_battler.move_frequency != 6 # スキル取得 skill = $data_skills[@attacker.current_action.skill_id] # スキルターゲット判定 targets = check_skill_target(skill, position) if [8, 11].include?(@now_scope) targets[1] += target_in_area($game_system.tactics_enemies.keys) end @fix_targets = targets if targets[1].size > 0 @targets = {} @total_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 @total_targets[i] = @targets[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 else # 最も近いバトラー取得 case @now_scope when 0, 1, 2, 5, 6, 9 id = nearest_battler($game_system.tactics_actors.keys) @target_position = [$game_map.events[id].x, $game_map.events[id].y] when 3, 4, 7, 10 id = nearest_battler($game_system.tactics_enemies.keys) @target_position = [$game_map.events[id].x, $game_map.events[id].y] when 8, 11 id = nearest_battler($game_system.tactics_actors.keys + $game_system.tactics_enemies.keys) @target_position = [$game_map.events[id].x, $game_map.events[id].y] end end else # 最も近いアクター取得 id = nearest_battler($game_system.tactics_actors.keys) @target_position = [$game_map.events[id].x, $game_map.events[id].y] end sa = (@active_battler.x - @target_position[0]).abs + (@active_battler.y - @target_position[1]).abs move = $game_system.tactics_enemies[@active_battler.id].movable # 移動頻度で移動範囲を分岐 if @active_battler.move_frequency != 6 if sa > (move * ZTBS::MOVEABLE_SA[@active_battler.move_frequency - 1]).ceil $game_system.tactics_step = 10 return end end # 移動エリア検索 search_route # 逃げる の場合 if @attacker.current_action.kind == 0 and @attacker.current_action.basic == 2 # 移動先決定 @target_position = far_away_position(@target_position, @position) else # 移動先決定 @target_position = nearest_position(@target_position, @position) end # 移動エリアをセット set_movable_area(1) # ステップを 3 に設定 $game_system.tactics_step = 3 end #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 5 : アクション再判定) #-------------------------------------------------------------------------- def update_phase2_step5 @wait_count = ZTBS::ENEMY_THINKING # 防御 or 何もしない の場合 if @attacker.current_action.kind == 0 and (@attacker.current_action.basic == 1 or @attacker.current_action.basic == 3) # ステップを 10 に設定 $game_system.tactics_step = 10 return 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 [8, 11].include?(@now_scope) ts = targets[1].select{|i| $game_system.tactics_actors.keys.include?(i)} else ts = targets[1] end if ts.size > 0 @targets = {} @total_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 else targets = battlers_in_area(position) @fix_targets = targets if targets.size > 0 @targets = {} @total_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) if [8, 11].include?(@now_scope) targets[1] += target_in_area($game_system.tactics_enemies.keys) end @fix_targets = targets if targets[1].size > 0 @targets = {} @total_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 #-------------------------------------------------------------------------- # ● フレーム更新 (エネミーフェーズ ステップ 6 : 対象選択) #-------------------------------------------------------------------------- def update_phase2_step6 # カーソル位置のバトラー(イベント)取得 get_cursor_battler # カーソル位置にバトラーがいる場合 if @battler != nil # ヘルプウィンドウにアクター or エネミーをセット set_battler_info # カーソル位置にバトラーがいない場合、ヘルプウィンドウを隠す else @help_window.visible = false end # 現在カーソル位置記憶 @now_x = $game_player.x @now_y = $game_player.y # カーソル固定を解除 $game_player.not_update = false # 移動中の場合 if !move_cursor_auto(@target_position) return end # アクション結果作成 case @attacker.current_action.kind when 0 make_basic_action_result when 1 make_skill_action_result end # 対象が全体でない場合 unless [2, 4, 6, 8].include?(@now_scope) # ハッシュの中身を1つにする key = @targets.keys[0] value = @targets[key] @targets.clear @targets[key] = value end # 互いに向き合う for i in @targets.keys $game_map.events[i].turn_toward_event(@active_battler.id) end @active_battler.turn_toward_position($game_player.x, $game_player.y) # エリア解放 dispose_area # ステップを 7 に設定 $game_system.tactics_step = 7 end end