!#============================================================================== # [ZTBS] -Zenith Tactical Battle System- タクティカルバトルシステム #  〜+B7:バトラー会話イベント設定〜   by 水夜 #  ver0.90  Zenith Creation (http://zenith.ifdef.jp/) #------------------------------------------------------------------------------ # マップ上での戦略的なバトルを実現。 #============================================================================== #============================================================================== # ■ Game_Map #============================================================================== class Game_Map #-------------------------------------------------------------------------- # ● ある地点のイベント取得 #-------------------------------------------------------------------------- def point_events(x, y) result = [] for event in self.events if event[1].x == x and event[1].y == y result.push(event) end end return result end end #============================================================================== # ■ Window_Command #============================================================================== class Window_Command < Window_Selectable attr_reader :commands end #============================================================================== # ■ Interpreter #============================================================================== class Interpreter def add_event(actor_id, reserve_id, common_id) $scene.talk_events[reserve_id] = [actor_id, common_id] end end #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :talk_events # 会話イベントのハッシュ #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- unless defined?(ZTBS::ZTBSB7_DEFINED) alias ztbsb7_initialize initialize def initialize @talk_events = talk_event ztbsb7_initialize end end #-------------------------------------------------------------------------- # ● カスタマイズ #-------------------------------------------------------------------------- def talk_event case $game_map.map_id #============================================================================== # ↓↓設定箇所は説明の下にあります↓↓ #============================================================================== #------------------------------------------------------------------------------ # when タクティカルマップID # return {される側ID => [する側ID, コモンイベントID] ...} #------------------------------------------------------------------------------ # # ※指定したIDのイベントに設定されたバトラーと隣接すると # 「会話」コマンドが出て、指定したIDのコモンイベントが実行されます。 # #============================================================================== # ここより下が設定箇所です #============================================================================== when 21 # マップID 2 return {18=>["all", 56] , 2=>["all", 2]} when 3 # マップID 3 return {} #============================================================================== # ここより上で設定してください #============================================================================== else return {} end end #-------------------------------------------------------------------------- # ● タクティクス初期セットアップ #-------------------------------------------------------------------------- def setup # ターンカウント初期化 $game_system.tactics_turn = 0 # すり抜け状態と移動速度を記憶 $game_player.through_original = $game_player.through $game_player.speed_original = $game_player.move_speed # すり抜け ON と 速度 $game_player.through = true $game_player.move_speed = ZTBS::CURSOR_SPEED # ヘルプウィンドウを作成 @help_window = Window_Help.new @help_window.back_opacity = 200 @help_window.visible = false # アクターとエネミーのセットアップ clear_battler setup_actors setup_enemies # ダメージをクリア for actor in $game_system.tactics_actors.values + $game_system.tactics_dead_actors.values actor.damage = nil end # ここに色々と追加する @talk_events = talk_event # フェーズを 0 に設定 $game_system.tactics_phase = 0 $game_system.tactics_step = 0 # カーソル固定 $game_player.not_update = true # 初期セットアップ完了フラグ $game_system.tactics_setup = true @select = nil @revival = nil @end_map = nil @level_up = nil @gold = nil @treasures = nil end #-------------------------------------------------------------------------- # ● コマンドウィンドウ作成 #-------------------------------------------------------------------------- def make_command_window(index = 0) case $game_system.tactics_step when 0 if defined?(ZTBSB6) @command_window = Window_Command.new(170, ZTBSB6::COMMANDS) else commands = [] commands.push("アクター一覧") commands.push("ターン終了") if !defined?(XRXS_CP_SYSTEM) commands.push("セーブ") if ZTBS::POSSIBLE_SAVE commands.push("タイトルに戻る") @command_window = Window_Command.new(170, commands) end @command_window.x = 0 @command_window.y = 64 when 2 commands = [] commands.push("移動") commands.push($data_system.words.attack) commands.push($data_system.words.guard) commands.push($data_system.words.skill) commands.push($data_system.words.item) commands.push("待機") if defined?(XRXS_CP_SYSTEM) commands += add_commands @command_window = Window_Command.new(120, commands) @command_window.x = 0 @command_window.y = 64 when 5 commands = [] commands.push($data_system.words.attack) commands.push($data_system.words.guard) commands.push($data_system.words.skill) commands.push($data_system.words.item) commands.push("待機") commands += add_commands @command_window = Window_Command.new(120, commands) @command_window.x = 0 @command_window.y = 64 end if @command_window != nil @command_window.back_opacity = 200 @command_window.index = index if $game_player.y < 4 @command_window.y = 416 - @command_window.height end if $game_player.x < 10 @command_window.x = 640 - @command_window.width end end end #-------------------------------------------------------------------------- # ● 発動可能判定 #-------------------------------------------------------------------------- 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 @can_attack = target_in_area($game_system.tactics_enemies.keys) if defined? @attacker.attack_range and @attacker.attack_range != nil battler_exist = @attacker.attack_range[1][3] else battler_exist = true 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] case skill.scope when 0 return false when 1, 2 @can_attack = target_in_area($game_system.tactics_enemies.keys) when 3, 4 @can_attack = target_in_area($game_system.tactics_actors.keys) when 5, 6 return true end when 2 item = $data_items[@attacker.current_action.item_id] battler_exist = item.range[1][3] case item.scope when 0 return false when 1, 2 @can_attack = target_in_area($game_system.tactics_enemies.keys) when 3, 4 @can_attack = target_in_area($game_system.tactics_actors.keys) when 5, 6 return true 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 #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ ステップ 2 : 移動前コマンド) #-------------------------------------------------------------------------- def update_phase1_step2 # B ボタンが押された場合 if Input.trigger?(Input::B) # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # コマンドウィンドウを解放 dispose_command_window # カーソル固定を解除 $game_player.not_update = false # ステップ 1 へ移行 $game_system.tactics_step = 1 end # C ボタンが押された場合 if Input.trigger?(Input::C) # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # コマンドによって分岐 case @command_window.index # 移動 when 0 # コマンドウィンドウ解放 dispose_command_window # 移動エリアをセット set_movable_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 3 へ移行 $game_system.tactics_step = 3 # 行動バトラー設定 @active_battler = @battler # 攻撃 when 1 # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 0 # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 # ステップ 2 帰還フラグ @back_step2 = true # 防御 when 2 # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # 防御状態に設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 1 # カーソル固定を解除 $game_player.not_update = false # ステップ 10 へ移行 $game_system.tactics_step = 10 # ステップ 2 帰還フラグ @back_step2 = true # スキル when 3 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 2 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(1, @attacker) # アクションを設定 @attacker.current_action.kind = 1 # ステップ 2 帰還フラグ @back_step2 = true # アイテム when 4 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 3 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(2) # アクションを設定 @attacker.current_action.kind = 2 # ステップ 2 帰還フラグ @back_step2 = true # その他 else if defined?("talk_event") # 「待機」のための分岐 if defined?(XRXS_CP_SYSTEM) and @command_window.index == 5 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 else @comindex = @command_window.index @comvalue = @command_window.commands[@comindex] # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = @comindex # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 # ステップ 2 帰還フラグ @back_step2 = true end # 待機 else # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 end end end end #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ ステップ 5 : 移動後コマンド) #-------------------------------------------------------------------------- def update_phase1_step5 # B ボタンが押された場合 if Input.trigger?(Input::B) # キャンセル SE を演奏 $game_system.se_play($data_system.cancel_se) # コマンドウィンドウ解放 dispose_command_window # 元の位置に戻す @active_battler.moveto(@pre_x, @pre_y) # カーソル位置を戻す back_cursor # 移動エリアをセット set_movable_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 3 へ移行 $game_system.tactics_step = 3 end # C ボタンが押された場合 if Input.trigger?(Input::C) # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # コマンドによって分岐 case @command_window.index # 攻撃 when 0 # コマンドウィンドウ解放 dispose_command_window # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 0 # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 # 防御 when 1 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # 防御状態に設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = 1 # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 # スキル when 2 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 1 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(1, @attacker) # アクションを設定 @attacker.current_action.kind = 1 # アイテム when 3 # コマンドウィンドウ解放 dispose_command_window # セレクト へ移行 @select = 2 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # セレクトウィンドウを作成 make_select_window(2) # アクションを設定 @attacker.current_action.kind = 2 # 待機 when 4 # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # コマンドウィンドウ解放 dispose_command_window # ステップ 10 へ移行 $game_system.tactics_step = 10 # その他 else @comindex = @command_window.index @comvalue = @command_window.commands[@comindex] # コマンドウィンドウ解放 dispose_command_window # 行動バトラー設定 @active_battler = @battler # 攻撃バトラー取得 @attacker = $game_system.tactics_actors[@active_battler.id] # アクションを設定 @attacker.current_action.kind = 0 @attacker.current_action.basic = @comindex # 攻撃エリアをセット set_attack_area(0) # カーソル固定を解除 $game_player.not_update = false # ステップ 6 へ移行 $game_system.tactics_step = 6 end end end #-------------------------------------------------------------------------- # ● フレーム更新 (アクターフェーズ ステップ 6 : 対象選択) #-------------------------------------------------------------------------- def update_phase1_step6 # カーソル位置のバトラー(イベント)取得 get_cursor_battler # ヘルプウィンドウにアクター or エネミーをセット set_battler_info # 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) else @targets[i] = $game_system.tactics_enemies[i] $game_map.events[i].turn_toward_event(@active_battler.id) end end @active_battler.turn_toward_position($game_player.x, $game_player.y) # 戦闘不能回復の場合 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 #-------------------------------------------------------------------------- # ● 実行するID #-------------------------------------------------------------------------- def cando_id(x, y) for event in $game_map.point_events(x, y) if @talk_events.keys.include?(event[1].id) return(event[1].id) end end end #-------------------------------------------------------------------------- # ● コマンドが実行可能か #-------------------------------------------------------------------------- def can_command?(x, y, name) for event in $game_map.point_events(x, y) can_actor = (@talk_events[event[1].id] != nil and (@talk_events[event[1].id][0] == $game_system.tactics_actors[@active_battler.id].id or @talk_events[event[1].id][0] == "all")) if @talk_events.keys.include?(event[1].id) and can_actor if event[1].name =~ /^(actor|enemy)\d+/ return(name == "会話") else return(name == event[1].name) end end end return false end #-------------------------------------------------------------------------- # ● コマンド追加 #-------------------------------------------------------------------------- def add_commands result = [] x = @battler.x y = @battler.y events = $game_map.point_events(x + 1, y) + $game_map.point_events(x - 1, y) + $game_map.point_events(x, y + 1) + $game_map.point_events(x, y - 1) for event in events can_actor = (@talk_events[event[1].id] != nil and (@talk_events[event[1].id][0] == $game_system.tactics_actors[@active_battler.id].id or @talk_events[event[1].id][0] == "all")) if @talk_events.keys.include?(event[1].id) and can_actor if event[1].name =~ /^(actor|enemy)\d+/ result.push("会話") else result.push(event[1].name) end end end return result.uniq.sort end #-------------------------------------------------------------------------- # ● 攻撃エリア検索 #-------------------------------------------------------------------------- def search_attack_area position = [[@battler.x, @battler.y]] if $game_system.tactics_actors.keys.include?(@battler.id) battler = $game_system.tactics_actors[@battler.id] else battler = $game_system.tactics_enemies[@battler.id] end case battler.current_action.kind when 0 if battler.current_action.basic < 4 if (defined? ACTOR_RANGE and @attacker.is_a?(Game_Actor)) or (defined? ENEMY_RANGE and @attacker.is_a?(Game_Enemy)) form = battler.attack_range[0][0] max = battler.attack_range[0][1] through = battler.attack_range[0][2] cannot_near = battler.attack_range[0][3] if cannot_near == nil cannot_near = false end else form = 0 max = 1 through = false cannot_near = false end if battler.is_a?(Game_Actor) type = 1 else type = 0 end else form = 0 max = 1 through = true cannot_near = false type = 1 end when 1 skill = $data_skills[battler.current_action.skill_id] form = skill.range[0][0] max = skill.range[0][1] through = skill.range[0][2] cannot_near = skill.range[0][3] if cannot_near == nil cannot_near = false end return position if max == 0 case skill.scope when 0, 5, 6 type = 4 when 1, 2 if battler.is_a?(Game_Actor) type = 1 else type = 0 end when 3, 4 if battler.is_a?(Game_Actor) type = 0 else type = 1 end when 7 return position end when 2 item = $data_items[battler.current_action.item_id] form = item.range[0][0] max = item.range[0][1] through = item.range[0][2] cannot_near = item.range[0][3] if cannot_near == nil cannot_near = false end case item.scope when 0, 5, 6 type = 4 when 1, 2 if battler.is_a?(Game_Actor) type = 1 else type = 0 end when 3, 4 if battler.is_a?(Game_Actor) type = 0 else type = 1 end when 7 return position end end more_step = [0] route = [[]] case form # ひし形or四角形の場合 when 0, 2, 3 if form == 2 or form == 3 max *= 2 end for i in more_step x = position[i][0] y = position[i][1] # 障害物無視の場合 if through # 下 if !position.include?([x, y + 1]) position.push([x, y + 1]) route.push(route[i] + [2]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [2])) end end # 左 if !position.include?([x - 1, y]) position.push([x - 1, y]) route.push(route[i] + [4]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [4])) end end # 右 if !position.include?([x + 1, y]) position.push([x + 1, y]) route.push(route[i] + [6]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [6])) end end # 上 if !position.include?([x, y - 1]) position.push([x, y - 1]) route.push(route[i] + [8]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [8])) end end # 障害物無視でない場合 else # 下 if !position.include?([x, y + 1]) and !on_area?(x, y, type) and (@battler.passable?(x, y, 2) or (on_area?(x, y + 1, type) and type != 4)) position.push([x, y + 1]) route.push(route[i] + [2]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [2])) end end # 左 if !position.include?([x - 1, y]) and !on_area?(x, y, type) and (@battler.passable?(x, y, 4) or (on_area?(x - 1, y, type) and type != 4)) position.push([x - 1, y]) route.push(route[i] + [4]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [4])) end end # 右 if !position.include?([x + 1, y]) and !on_area?(x, y, type) and (@battler.passable?(x, y, 6) or (on_area?(x + 1, y, type) and type != 4)) position.push([x + 1, y]) route.push(route[i] + [6]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [6])) end end # 上 if !position.include?([x, y - 1]) and !on_area?(x, y, type) and (@battler.passable?(x, y, 8) or (on_area?(x, y - 1, type) and type != 4)) position.push([x, y - 1]) route.push(route[i] + [8]) if route[i].size + 1 < max more_step.push(route.index(route[i] + [8])) end end end end # 四角形の場合 case form when 2 delete = [] for pos in position if (pos[0] - @battler.x).abs > max/2 or (pos[1] - @battler.y).abs > max/2 delete.push(pos) end end for i in delete position.delete(i) end when 3 delete = [] for pos in position if (pos[0] - @battler.x).abs != max/2 and (pos[1] - @battler.y).abs != max/2 delete.push(pos) end end for i in delete position.delete(i) end return position end # 十字形の場合 when 1 for i in 1..max x = position[0][0] y = position[0][1] # 障害物無視の場合 if through position.push([x, y + i]) position.push([x - i, y]) position.push([x + i, y]) position.push([x, y - i]) # 障害物無視でない場合 else if position.include?([x, y + i - 1]) and !on_area?(x, y + i - 1, type) and (@battler.passable?(x, y + i - 1, 2) or on_area?(x, y + i, type)) position.push([x, y + i]) end if position.include?([x - i + 1, y]) and !on_area?(x - i + 1, y, type) and (@battler.passable?(x - i + 1, y, 4) or on_area?(x - i, y, type)) position.push([x - i, y]) end if position.include?([x + i - 1, y]) and !on_area?(x + i - 1, y, type) and (@battler.passable?(x + i - 1, y, 6) or on_area?(x + i, y, type)) position.push([x + i, y]) end if position.include?([x, y - i + 1]) and !on_area?(x, y - i + 1, type) and (@battler.passable?(x, y - i + 1, 8) or on_area?(x, y - i, type)) position.push([x, y - i]) end end end end # 自分を除くかどうか case battler.current_action.kind when 0 position.shift when 1 if [1, 2, 5, 6].include?(skill.scope) position.shift end when 2 if [1, 2, 5, 6].include?(item.scope) position.shift end end # 近接不可の場合 if cannot_near position.delete([@battler.x, @battler.y + 1]) position.delete([@battler.x - 1, @battler.y]) position.delete([@battler.x + 1, @battler.y]) position.delete([@battler.x, @battler.y - 1]) end return position end end #============================================================================== # ■ ZTBS #============================================================================== module ZTBS ZTBSB7_DEFINED = true end