#◆◇◆◇◆ ☆☆ AIシステム ver 1.07 ◇◆◇◆◇ # ☆☆ マスタースクリプト ver 3.00 以降専用 # サポート掲示板 http://www2.ezbbs.net/21/minto-aaa/ # by みんと #◆◇◆◇◆ Active Count Battle 2 - KGC_ActiveCountBattle2 ◇◆◇◆◇ # サポート先 http://ytomy.sakura.ne.jp/(KGC Software) # 作者 TOMY # ※ Active Count Battle 2 はKGC Softwareさんの著作物です。 # 本スクリプトはKGC Softwareさんの # Active Count Battle 2 に対応してはおりますが、 # KGC Softwareさんのライセンス・スクリプトではありません。 # また、KGC Softwareさんの # すべてのスクリプトとの動作を保証するものでもありません。 # 本スクリプトの不具合などをKGC Softwareさんの # 掲示板などに書き込まないようお願いいたします。 =begin 更新記録 ver 1.07 KGC Softwareさんの ACB2併用におけるエラー落ちを修正 ver 1.06 KGC SoftwareさんのActiveCountBattle2に対応 (簡単なテストしかしてません(´・ω・`)) ver 1.05 援護行動時のエラーを修正 ver 1.04 一部の思考ロジックのミスを再修正 ver 1.03 一部の思考ロジックのミスを再修正 ver 1.02 ソースの移植ミスを修正 ver 1.01 一部の思考ロジックのミスを修正 説明 みんとのお部屋、10万ヒット記念スクリプトです(ナニ 思考ロジックによるAI行動をアクターに搭載できます。 思考ロジックは、プレイヤーがカスタマイズすることが出来て、 4つまでセーブデータに記憶されるので、任意で切り替えることが可能です。 カスタマイズできる思考ロジックは メイン思考タイプ ターゲット優先度 攻撃頻度 回復頻度の4つです。 メイン思考ロジックは 回復に専念しろ (回復、浄化以外のスキルを使わない) 力を温存しろ (SPが75%以下になるまで25%の確率でスキルを使用する) バランス重視 (SPが50%以下になるまで50%の確率でスキルを使用する) 味方を援護しろ (SPが50%以下になるまで75%の確率でスキルを使用し、援護を優先する) 敵を妨害しろ (SPが50%以下になるまで75%の確率でスキルを使用し、妨害を優先する) 援護を優先しろ (SPが25%以下になるまで90%の確率でスキルを使用し、援護を最優先する) 妨害を優先しろ (SPが25%以下になるまで90%の確率でスキルを使用し、妨害を最優先する) まとめて倒せ (SPが25%以下になるまで90%の確率でスキルを使用し、全体攻撃を優先する) 確実に倒せ (SPを気にせずスキルを使用し、威力を最優先する) の9つです。 ターゲット優先度は 弱った敵を狙え (残りHPの割合が低い敵を優先する) 元気な敵を狙え (残りHPの割合が高い敵を優先する) 力のある敵を狙え (攻撃力が高い敵を優先する) 硬い敵を狙え (防御力が高い敵を優先する) もろい敵を狙え (防御力が低い敵を優先する) 魔防の高い敵を狙え (魔法防御力が高い敵を優先する) 魔防の低い敵を狙え (魔法防御力が低い敵を優先する) 速い敵を狙え (素早さが高い敵を優先する) 遅い敵を狙え (素早さが低い敵を優先する) の9つです。 攻撃頻度は6段階に分かれていて 0 一切攻撃を行わず、防御と回復と浄化のみの行動になる。 1 HPが90%以下になると90%の確率で防御する。 2 HPが75%以下になると75%の確率で防御する。 3 HPが50%以下になると50%の確率で防御する。 4 HPが25%以下になると25%の確率で防御する。 5 一切防御を行わない。 となっています。 回復頻度も6段階で 0 一切回復を行わず、浄化のみを行う。 1 HPが15%以下の味方にスキルによる回復を行う。 2 HPが35%以下の味方にスキルによる回復を行う。 3 HPが50%以下の味方にスキルによる回復を行う。 4 HPが75%以下の味方にスキルによる回復を行う。 5 HPが99%以下の味方にスキルによる回復を行う。 となっています。 イベントのスクリプトで キャラの操作モードを変更するには $game_actors[ID].ai = true のように入力してください。 true でオート false でマニュアルです。 また、操作モードを固定にするには $game_actors[ID].not_control = true のように入力してください。 true で操作モードの変更が出来なくなります。 思考ロジックすら固定の場合は $game_actors[ID].not_operation = true のように入力してください。 true で思考ロジックの変更が出来なくなります。 イベントのスクリプトで作戦画面を実行するには Utility_Operation.new と入力してください。 $scene = Utility_Operation.new とは入力せずに 必ず Utility_Operation.new のみの入力を行ってください。 マップなどのシーンを問わず、現状の画面を保持したまま、 作戦画面が実行されます。 現状では、戦闘画面とメニュー画面から実行できます。 準備設定 まずは、属性で 有効 と 有害 という名前の2つの属性を用意してください。 そしてそれらを、 AIキャラに使わせたい「ステート」の防御属性にセットしてください。 有効属性がセットされていれば、有効ステートとして認識し、 有害属性がセットされていれば、有害ステートとして認識します。 援護の際は、それらのスキルを使用します。 有効、有害の優先順位は ステートのレーティングがそのまま反映されます。 0の場合は使用の候補に入りません。 仕様 以下はAIシステムの仕様です。 AIキャラは原則的に ・絶対当たらないスキル ・無効、吸収される攻撃スキル ・命中率が最大のものと比較して 2/1 以内に収まらないスキル (ファイア49%、サンダー100%、アクア75%ならファイアは威力を問わず使用しない) ・第二命中率が60%以下、付加成功率が30以下の毒などの妨害系スキル ・有効ステートが設定されていても、 他の有効ステートが解除されて、結果的に弱くなるスキル。 は一切使用しません。 予めご了承ください。 =end #============================================================================== # ☆ MINTO #------------------------------------------------------------------------------ # 様々なフラグを扱うメインモジュールです。 #============================================================================== module MINTO # AIシステムを有効化 ( true で有効 / false で無効 ) RGSS["AI_System"] = true end if MINTO::RGSS["AI_System"] == true then #============================================================================== # ☆ カスタマイズ #------------------------------------------------------------------------------ # 機能のカスタマイズを行うモジュールです。 #============================================================================== module MINTO # メニューから作戦画面に移行するキー Operation_Key = Input::A #-------------------------------------------------------------------------- # ● KGC Softwareスクリプトの検索 # key : スクリプトキー #-------------------------------------------------------------------------- def self.search_kgc(key) # 指定されたスクリプトが有効かどうか調べる $imported != nil and $imported[key] == true end end #============================================================================== # ■ RPG::State #------------------------------------------------------------------------------ #  ステートを扱う組み込みクラスです。 #============================================================================== module RPG class State #------------------------------------------------------------------------ # ● 有効度の取得 #------------------------------------------------------------------------ def valid_point # 属性「有効」の取得 valid = Data_System.data.elements.index("有効") # 属性「有害」の取得 bad = Data_System.data.elements.index("有害") # 属性「有効」が付加されている場合 if self.guard_element_set.include?(valid) == true then # レーティングを返す return self.rating # 属性「有害」が付加されている場合 elsif self.guard_element_set.include?(bad) == true then # レーティングを反転させて返す return self.rating * -1 # そのほかのステートの場合 else # 0 を返す return 0 end end end end #============================================================================== # ■ RPG::Skill #------------------------------------------------------------------------------ #  スキルを扱う組み込みクラスです。 #============================================================================== module RPG class Skill #------------------------------------------------------------------------ # ● 解除有効判定 # status : 対象のステート #------------------------------------------------------------------------ def mute_state?(status) # ステートを順番に処理にかける status.each do |i| # 解除ステートの配列に含まれている場合 if minus_state_set.include?(i) # フラグを返す return true end end # フラグを返す return false end #------------------------------------------------------------------------ # ● 援護スキル判定 #------------------------------------------------------------------------ def support? # 1つでも付加する効果がある場合 if plus_state_set.size >= 1 # フラグを返す return true end # 1つでも解除する効果がある場合 if minus_state_set.size >= 1 # フラグを返す return true end # フラグを返す return false end #------------------------------------------------------------------------ # ● 有効度の取得 #------------------------------------------------------------------------ def valid_point # 有効度を初期化 valid = 0 # 付加ステートの配列を複製して取得する plus_state = plus_state_set.dup # ステートの数だけ繰り返す plus_state.each do |i| # ステートの有効度を加算する valid += Data_States.data[i].valid_point end # 有効度を返す return valid end end end #============================================================================== # ■ Game_Battler (分割定義 1) #------------------------------------------------------------------------------ #  バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ # スのスーパークラスとして使用されます。 #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :ai_type # AIのタイプの配列 attr_accessor :target # AI用のターゲット attr_accessor :ai # AIフラグ attr_accessor :not_control # 操作固定フラグ attr_accessor :not_operation # 作戦固定フラグ attr_accessor :states # ステート #-------------------------------------------------------------------------- # ● オブジェクト初期化 # alias : initialize_MINTO_Ai_System #-------------------------------------------------------------------------- alias initialize_MINTO_Ai_System initialize def initialize # 元の処理を実行 initialize_MINTO_Ai_System @ai_type = [3, 3, "バランス重視", "弱った敵を狙え"] @target = [] @ai = false @not_control = false @not_operation = false end end #============================================================================== # ■ Game_Battler (分割定義 4) #------------------------------------------------------------------------------ #  バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ # スのスーパークラスとして使用されます。 #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # ● 第二命中判定 # attacker : 攻撃者 (バトラー) # skill : スキル #-------------------------------------------------------------------------- def hit_percent(attacker, i = nil) # スキル攻撃でない場合 if i == nil then # 第二命中判定 eva = 8 * self.agi / attacker.dex + self.eva hit = 100 - eva hit = self.cant_evade? ? 100 : hit else skill = Data_Skills_Base.data[i] # 第二命中判定 eva = 8 * self.agi / attacker.dex + self.eva hit = 100 - eva * skill.eva_f / 100 hit = self.cant_evade? ? 100 : hit end # 値を返す return hit end #-------------------------------------------------------------------------- # ● 攻撃のダメージ予想 # attacker : 攻撃者 (バトラー) # skill : スキル #-------------------------------------------------------------------------- def attack_damage2(attacker, skill = nil) # スキルの場合 if skill != nil # スキルの効果を予想 return skill_damage(attacker, skill) end # 基本ダメージを計算 atk = [attacker.atk - self.pdef / 2, 0].max damage = atk * (20 + attacker.str) / 20 # 属性修正 damage *= elements_correct(attacker.element_set) damage /= 100 # メソッド終了 return damage end #-------------------------------------------------------------------------- # ● スキルのダメージ予想 # user : スキルの使用者 (バトラー) # skill : スキル #-------------------------------------------------------------------------- def skill_damage(user, i) skill = Data_Skills_Base.data[i] # 威力を計算 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 # メソッド終了 return damage end #-------------------------------------------------------------------------- # ● 全体スキルのターゲットの取得 # scope : スキルの効果範囲 #-------------------------------------------------------------------------- def set_target(scope) @target = [] # 行動側バトラーがエネミーの場合 if self.is_a?(Game_Enemy) == true then # 効果範囲で分岐 case scope # 敵全体 when 2 then for battler in $game_party.actors do if battler.exist? == true then @target.push(battler) end end # 味方全体 when 4 then for enemy in $game_troop.enemies do if enemy.exist? == true then @target.push(enemy) end end # 味方全体 (HP 0) when 6 then for enemy in $game_troop.enemies do if enemy != nil and enemy.hp0? == true then @target.push(enemy) end end end end # 行動側バトラーがアクターの場合 if self.is_a?(Game_Actor) == true then # 効果範囲で分岐 case scope # 敵全体 when 2 then for enemy in $game_troop.enemies do if enemy.exist? == true then @target.push(enemy) end end # 味方全体 when 4 then for battler in $game_party.actors do if battler.exist? == true then @target.push(battler) end end # 味方全体 (HP 0) when 6 then for battler in $game_party.actors do if battler != nil and battler.hp0? == true then @target.push(battler) end end end end end #-------------------------------------------------------------------------- # ● 付加成功率の取得 # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_plus_state_rate(skill) # 最高成功率を定義 max_percent = 0 # 付加するステートが1つでもある場合 if skill.plus_state_set.size >= 1 then # 付加ステートを順番に処理にかける skill.plus_state_set.each do |plus_id| # 対象のステートが無効な場合 if state_guard?(plus_id) == true then # 次の候補へ next # そのステートが付加されている場合 elsif @states.include?(plus_id) then # 次の候補へ next end # ステートの付加成功率を取得する plus_percent = [0,100,80,60,40,20,0][state_ranks[plus_id]] # 最高成功率より高い場合 if plus_percent > max_percent then # 最高成功率を更新 max_percent = plus_percent end end end # 最高成功率を返す return max_percent end #-------------------------------------------------------------------------- # ● 仮想HPの取得 # target : 対象ターゲット #-------------------------------------------------------------------------- def virtual_hp(target) # HPを取得 virtual_hp = target.hp # 結果を返す return virtual_hp * 100 / target.maxhp end #-------------------------------------------------------------------------- # ● ステートの仮想有効度の取得 # skill : 行動者のスキル #-------------------------------------------------------------------------- def virtual_state_valid_point(skill) # 現在のステートを複製して取得する states_clone = self.states.dup # HPを保存 last_hp = self.hp # SPを保存 last_sp = self.sp # スキルステートを順番に処理にかける skill.plus_state_set.each do |i| # ステートを付加させる self.add_state(i) end # ステートを解除する self.states_minus(skill.minus_state_set) # ステートの有効度を取得する new_valid = self.state_valid_point # ステートを戻す self.states = states_clone.dup # HPを戻す self.hp = last_hp # SPを戻す self.sp = last_sp # 有効度を返す return new_valid end #-------------------------------------------------------------------------- # ● ステート有効度の取得 #-------------------------------------------------------------------------- def state_valid_point # 有効度を定義 valid = 0 # ステートの数だけ繰り返す @states.each do |i| # ステートの有効度を加算する valid += Data_States.data[i].valid_point end # 有効度を返す return valid end #-------------------------------------------------------------------------- # ● ステート有害度の取得 #-------------------------------------------------------------------------- def bad_state_valid_point # 有害度を定義 valid = 0 # ステートの数だけ繰り返す @states.each do |i| # ステートの有効度がマイナスの場合 if Data_States.data[i].valid_point <= -1 # 有害度を加算する valid += Data_States.data[i].valid_point end end # 有害度を返す return valid end #-------------------------------------------------------------------------- # ● ターゲットの選定 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def target_choice(target, skill) # 回復フラグを定義 @ai_type[4] = false # ターゲットが存在しない場合 if target == nil then # 回復可能な対象を取得 target = get_healing_battler(skill)[0] # 回復可能な対象がいない場合 if target == nil then # 浄化可能な対象を取得 target = get_clear_battler[0] # 浄化可能な対象がいない場合 if target == nil then # 攻撃可能な対象を取得 target = get_attack_enemy[0] else # 回復フラグを有効化 @ai_type[4] = true end else # 回復フラグを有効化 @ai_type[4] = true end end # ターゲットを返す return target end #-------------------------------------------------------------------------- # ● AI行動の決定 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def ai_action(target, skill) # すでに行動が決定している場合 if @ai_type[5] == true then # メソッドを返す return end # 制約が [敵を通常攻撃する] か [味方を通常攻撃する] の場合 if self.restriction == 2 or self.restriction == 3 then # メソッドを返す return end # ターゲットを取得する target = target_choice(target, skill) # スキルを複製 action_skills = skill.dup # スキルを対象に対して威力が低い順にソート action_skills.sort! do |a, b| a_str = Data_Skills_Base.data[a].str_f b_str = Data_Skills_Base.data[b].str_f target.attack_damage2(self, a) * [a_str, 1].max <=> target.attack_damage2(self, b) * [b_str, 1].max end # 回復フラグが有効な場合 if @ai_type[4] == true then # 回復行動の処理 effective = revival_skill_effect(target, action_skills) # 極端な処理落ちを防止する Graphics.frame_reset # 浄化行動の処理 effective ||= clear_skill_effect(target, action_skills) # 極端な処理落ちを防止する Graphics.frame_reset end # 通常行動の決定 effective ||= set_normal_action # 思考タイプが 回復に専念しろ 以外の場合 if @ai_type[2] != "回復に専念しろ" then # 通常スキル行動の処理 effective ||= normal_skill_effect(get_attack_enemy[0], action_skills) # 極端な処理落ちを防止する Graphics.frame_reset end # 使用した場合 if effective == true and self.current_action.basic != 1 then # スキルを取得 skill = Data_Skills_Base.data[self.current_action.skill_id] # 全体スキルだった場合 if skill.scope == 2 or skill.scope == 4 or skill.scope == 6 then # ターゲットを更新 set_target(skill.scope) else # ターゲットが未設定の場合 if self.target.to_a == [] then # ターゲットに設定 self.target = [target] end end # アクションを確定させる @ai_type[5] = true # 処理を終了 return end # 防御が確定している場合 if @ai_type[5] == true and self.current_action.basic == 1 then # メソッドを返す return end # 行動を通常攻撃に設定 self.current_action.kind = 0 self.current_action.basic = 0 self.target = [battle_target_choice(get_attack_enemy)] # アクションを確定させる @ai_type[5] = true # 極端な処理落ちを防止する Graphics.frame_reset end #-------------------------------------------------------------------------- # ● 通常行動の決定 #-------------------------------------------------------------------------- def set_normal_action # アクションモードを攻撃に設定 action_mode = 0 # 攻撃頻度に応じて分岐 case @ai_type[0] # 絶対防御 when 0 then # ガードフラグを代入 action_mode = 1 # 極高確率防御 when 1 then # HPが90%以下の場合 if virtual_hp(self) <= 90 then # 確率 90% をクリアした場合 if 90 > rand(100) # ガードフラグを代入 action_mode = 1 end end # 高確率防御 when 2 then # HPが75%以下の場合 if virtual_hp(self) <= 75 then # 確率 75% をクリアした場合 if 75 > rand(100) # ガードフラグを代入 action_mode = 1 end end # 中確率防御 when 3 then # HPが50%以下の場合 if virtual_hp(self) <= 50 then # 確率 50% をクリアした場合 if 50 > rand(100) # ガードフラグを代入 action_mode = 1 end end # 低確率防御 when 4 then # HPが25%以下の場合 if virtual_hp(self) <= 25 then # 確率 25% をクリアした場合 if 25 > rand(100) # ガードフラグを代入 action_mode = 1 end end end # アクションモードに応じて分岐 case action_mode # 通常攻撃 when 0 then # 不可フラグを設定 effective = false # 防御 when 1 then # 行動を防御に設定 self.current_action.kind = 0 self.current_action.basic = 1 # アクションを確定させる @ai_type[5] = true # 有効フラグを設定 effective = true end # フラグを返す return effective end #-------------------------------------------------------------------------- # ● 回復可能な対象を取得 # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_healing_battler(skill) # 行動者がアクターの場合 if self.is_a?(Game_Actor) == true then # パーティーを複製する battlers = $game_party.actors.dup # 行動者がエネミーの場合 else # トループを複製する battlers = $game_troop.enemies.dup end # バトラーをHPが低い順にソート battlers.sort! do |a, b| a.hp.rate(a.maxhp) <=> b.hp.rate(b.maxhp) end # HPの減っている対象がいない場合 if healing_action_ok?(battlers[0]) == false then # nil を返す return [nil] end # 蘇生スキルを持っていない場合 if revival_skill_exist?(skill) == false then # バトラーを順番に処理にかける battlers.each do |target| # 対象が戦闘不能な場合 if target.dead? == true then # 対象を候補から除外 battlers.delete(target) end end # 無効な候補を除外 battlers.compact! end # バトラーを返す return battlers end #-------------------------------------------------------------------------- # ● 浄化可能な対象を取得 #-------------------------------------------------------------------------- def get_clear_battler # 行動者がアクターの場合 if self.is_a?(Game_Actor) == true then # パーティーを複製する battlers = $game_party.actors.dup # 行動者がエネミーの場合 else # トループを複製する battlers = $game_troop.enemies.dup end # バトラーをステートの有効度が低い順にソート battlers.sort! do |a, b| a.bad_state_valid_point <=> b.bad_state_valid_point end # 有効度がマイナスの対象がいない場合 if battlers[0].bad_state_valid_point >= 0 then # nil を返す return [nil] end # ターゲット用の配列を作成 target_battlers = [] # バトラーを順番に処理にかける for target in battlers do # ターゲットが存在する場合 if target.exist? == true then # 配列に追加 target_battlers.push(target) end end # 対象を返す return target_battlers end #-------------------------------------------------------------------------- # ● 攻撃可能なエネミーを取得 #-------------------------------------------------------------------------- def get_attack_enemy # トループを複製する troop = $game_troop.enemies.dup # 思考タイプに応じてエネミーを並び替える case @ai_type[3] # 弱った敵を狙え when "弱った敵を狙え" then # トループをエネミーのHPが低い順にソート troop.sort! do |a, b| a.hp * 100 / a.maxhp <=> b.hp * 100 / b.maxhp end # 元気な敵を狙え when "元気な敵を狙え" then # トループをエネミーのHPが多い順にソート troop.sort! do |a, b| b.hp * 100 / b.maxhp <=> a.hp * 100 / a.maxhp end # 力のある敵を狙え when "力のある敵を狙え" then # トループをエネミーの腕力が高い順にソート troop.sort! do |a, b| b.str <=> a.str end # 硬い敵を狙え when "硬い敵を狙え" then # トループをエネミーの物理防御が高い順にソート troop.sort! do |a, b| b.pdef <=> a.pdef end # もろい敵を狙え when "もろい敵を狙え" then # トループをエネミーの物理防御が低い順にソート troop.sort! do |a, b| a.pdef <=> b.pdef end # 魔防の高い敵を狙え when "魔防の高い敵を狙え" then # トループをエネミーの魔法防御が高い順にソート troop.sort! do |a, b| b.mdef <=> a.mdef end # 魔防の低い敵を狙え when "魔防の低い敵を狙え" then # トループをエネミーの魔法防御が低い順にソート troop.sort! do |a, b| a.mdef <=> b.mdef end # 速い敵を狙え when "速い敵を狙え" then # トループをエネミーの素早さが高い順にソート troop.sort! do |a, b| b.agi <=> a.agi end # 遅い敵を狙え when "遅い敵を狙え" then # トループをエネミーの素早さが低い順にソート troop.sort! do |a, b| a.agi <=> b.agi end end # ターゲット用の配列を作成 troops = [] # トループを順番に処理にかける for target in troop do # エネミーが存在する場合 if target.exist? == true then # 配列に追加 troops.push(target) end end # 配列を返す return troops end #-------------------------------------------------------------------------- # ● ターゲットの選定 # target_array : 対象ターゲットの配列 #-------------------------------------------------------------------------- def battle_target_choice(target_array) # ターゲット用の配列を作成 target_battlers = [] # ターゲットの数だけ繰り返す (0...target_array.size).each do |i| # ループ回数の取得 loop_number = 9 - i # 回数分繰り返す loop_number.times do # ターゲットを配列に加算する target_battlers.push(target_array[i]) end end # 乱数からターゲットを得る target_battler = target_battlers[rand(target_battlers.size)] # ターゲットを返す return target_battler end #-------------------------------------------------------------------------- # ● 回復行動使用判定 # target : 対象ターゲット #-------------------------------------------------------------------------- def healing_action_ok?(target) # 回復を行うか判定 case @ai_type[1] # 絶対使わない when 0 then healing = false # 頻度極低 when 1 then # HPが15%以下の場合 if virtual_hp(target) <= 15 then # 使用フラグをオン healing = true end # 頻度低 when 2 then # HPが35%以下の場合 if virtual_hp(target) <= 35 then # 使用フラグをオン healing = true end # 頻度中 when 3 then # HPが50%以下の場合 if virtual_hp(target) <= 50 then # 使用フラグをオン healing = true end # 頻度高 when 4 then # HPが75%以下の場合 if virtual_hp(target) <= 75 then # 使用フラグをオン healing = true end # 頻度最高 when 5 then # HPが99%以下の場合 if virtual_hp(target) <= 99 then # 使用フラグをオン healing = true end end # フラグを返す return healing end #-------------------------------------------------------------------------- # ● スキル使用判定 #-------------------------------------------------------------------------- def attack_action_ok? # スキル許可フラグを定義 attack = false # 思考タイプに応じて分岐 case @ai_type[2] # 絶対使わない when "回復に専念しろ" then attack = false # 頻度低 when "力を温存しろ" then # SPが75%以下でない場合 if (self.sp * 100) / self.maxsp >= 75 then # 25% の確率をクリアした場合 if 25 > rand(100) # 使用フラグをオン attack = true end end # 頻度中 when "バランス重視" then # SPが50%以下でない場合 if (self.sp * 100) / self.maxsp >= 50 then # 50% の確率をクリアした場合 if 50 > rand(100) # 使用フラグをオン attack = true end end # 頻度中 when "味方を援護しろ" then # SPが50%以下でない場合 if (self.sp * 100) / self.maxsp >= 50 then # 75% の確率をクリアした場合 if 75 > rand(100) # 使用フラグをオン attack = true end end # 頻度中 when "敵を妨害しろ" then # SPが50%以下でない場合 if (self.sp * 100) / self.maxsp >= 50 then # 75% の確率をクリアした場合 if 75 > rand(100) # 使用フラグをオン attack = true end end # 頻度高 when "まとめて倒せ" then # SPが25%以下でない場合 if (self.sp * 100) / self.maxsp >= 25 then # 90% の確率をクリアした場合 if 90 > rand(100) # 使用フラグをオン attack = true end end # 頻度高 when "援護を優先しろ" then # SPが25%以下でない場合 if (self.sp * 100) / self.maxsp >= 25 then # 90% の確率をクリアした場合 if 90 > rand(100) # 使用フラグをオン attack = true end end # 頻度高 when "妨害を優先しろ" then # SPが25%以下でない場合 if (self.sp * 100) / self.maxsp >= 25 then # 90% の確率をクリアした場合 if 90 > rand(100) # 使用フラグをオン attack = true end end # 頻度最高 when "確実に倒せ" then # 使用フラグをオン attack = true end # フラグを返す return attack end #-------------------------------------------------------------------------- # ● スキルのバランス判定 #-------------------------------------------------------------------------- def get_attack_action # アクションのタイプを定義 type = [1, -1] # 思考タイプに応じて分岐 case @ai_type[2] # 力を温存しろ when "力を温存しろ" then # 25% の確率をクリアした場合 if 25 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 50% の確率をクリアした場合 if 50 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # バランスよく戦え when "バランス重視" then # 50% の確率をクリアした場合 if 50 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 50% の確率をクリアした場合 if 50 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # 味方の援護をしろ when "味方を援護しろ" then # 75% の確率をクリアした場合 if 75 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 90% の確率をクリアした場合 if 90 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # 敵を妨害しろ when "敵を妨害しろ" then # 75% の確率をクリアした場合 if 75 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 25% の確率をクリアした場合 if 25 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # 援護を優先しろ when "援護を優先しろ" then # 95% の確率をクリアした場合 if 95 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 95% の確率をクリアした場合 if 95 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # 妨害を優先しろ when "妨害を優先しろ" then # 90% の確率をクリアした場合 if 90 > rand(100) then # 援護スキルフラグを代入する type[0] = 0 end # 10% の確率をクリアした場合 if 10 > rand(100) then # 有効スキルフラグを代入する type[1] = 1 end # 確実に倒せ when "確実に倒せ" then # 攻撃スキルフラグを代入する type[0] = 1 # まとめて倒せ when "まとめて倒せ" then # 攻撃スキルフラグを代入する type[0] = 1 end # フラグを返す return type end #-------------------------------------------------------------------------- # ● 蘇生可能スキルの検索 # skill_array : 行動者のスキル #-------------------------------------------------------------------------- def revival_skill_exist?(skill_array) # 所持フラグを定義 revival_skill = false # スキルを順番に処理にかける skill_array.each do |i| # 引数がスキルの場合 if i.is_a?(RPG::Skill) == true then # スキルを取得 skill = i else # スキルを取得 skill = Data_Skills_Base.data[i] end # 範囲が HP0 の場合 if skill.scope == 5 or skill.scope == 6 then # そのスキルが使用可能な場合 if skill_can_use?(skill.id) == true then # フラグをオンにする revival_skill = true end end end # フラグを返す return revival_skill end #-------------------------------------------------------------------------- # ● 蘇生スキルの使用可能判定 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def revival_skill_ok?(target, skill) # スキルの効果範囲がHP0のいずれかの場合 if ((skill.scope == 5 or skill.scope == 6) and target.hp == 0) then # フラグを返す return true else # フラグを返す return false end end #-------------------------------------------------------------------------- # ● 使用可能な回復スキルの取得 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_healing_skill(target, action_skills) # スキル用の配列を生成 skill_array = [] # スキルの配列の中から検索 action_skills.each do |i| # 実際のスキルを取得 skill = Data_Skills_Base.data[i] # 威力がマイナスで且つ使用可能な場合 if skill.power <= -1 and skill_can_use?(skill.id) == true then # 蘇生スキルの場合、実行できるかチェック if revival_skill_ok?(target, skill) == true then # スキルの配列に追加 skill_array.push(skill) # 蘇生スキルでない場合 elsif skill.scope != 5 and skill.scope != 6 then # スキルの範囲が 自分 の場合 if skill.scope == 7 then # ターゲットが自分自身の場合 if target == self then # スキルの配列に追加 skill_array.push(skill) end else # スキルの配列に追加 skill_array.push(skill) end end end end # スキルを返す return skill_array end #-------------------------------------------------------------------------- # ● 使用可能な浄化スキルの取得 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_clear_skill(target, action_skills) # スキル用の配列を生成 skill_array = [] # スキルの配列の中から検索 action_skills.each do |i| # 実際のスキルを取得 skill = Data_Skills_Base.data[i] # そのスキルが使用できる場合 if skill_can_use?(skill.id) == true then # 範囲が 味方 の場合 if skill.scope == 3 or skill.scope == 4 then # 解除が設定されているステートが1つでもある場合 if skill.minus_state_set.size >= 1 then # スキルの配列に追加 skill_array.push(skill) end # スキルの範囲が 自分 の場合 elsif skill.scope == 7 then # ターゲットが自分自身の場合 if target == self then # スキルの配列に追加 skill_array.push(skill) end end end end # スキルを返す return skill_array end #-------------------------------------------------------------------------- # ● 使用可能な攻撃スキルの取得 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_attack_skill(target, action_skills) # スキル用の配列を生成 skill_array = [] # スキルの配列の中から検索 action_skills.each do |i| # 実際のスキルを取得 skill = Data_Skills_Base.data[i] # 威力がプラスで且つ使用可能な場合 if skill.power >= 1 and skill_can_use?(skill.id) == true then # 範囲が 敵 の場合 if skill.scope == 1 or skill.scope == 2 then # スキルの配列に追加 skill_array.push(skill) end end end # スキルを返す return skill_array end #-------------------------------------------------------------------------- # ● 使用可能な援護スキルの取得 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def get_support_skill(target, action_skills) # スキル用の配列を生成 skill_array = [] # スキルの配列の中から検索 action_skills.each do |i| # 実際のスキルを取得 skill = Data_Skills_Base.data[i] # スキルが使用可能な場合 if skill_can_use?(i) == true then # 命中値を取得 skill_hit = target.hit_percent(self, skill.id) # 命中率が 60 以上の場合 if skill_hit >= 60 then # 援護スキルの場合 if skill.support? == true then # 付加成功率が 30 以上の場合 if target.get_plus_state_rate(skill) >= 30 then # スキルの範囲が 自分 の場合 if skill.scope == 7 then # ターゲットが自分自身の場合 if target == self then # スキルの配列に追加 skill_array.push(skill) end # スキルの範囲が 自分 以外の場合 else # スキルの配列に追加 skill_array.push(skill) end end end end end end # 使用できるスキルをソート skill_array.sort! do |a, b| # 命中値 A を取得 a_hit = target.hit_percent(self, a.id) # 命中値 B を取得 b_hit = target.hit_percent(self, b.id) # 命中値に変化がない場合 if a_hit == b_hit then # 威力が高い順に並び替える target.attack_damage2(self, a.id) * [a.str_f, 1].max <=> target.attack_damage2(self, b.id) * [b.str_f, 1].max # 命中値が異なる場合 else # 命中値が高い順に並び替える target.hit_percent(self, b.id) <=> target.hit_percent(self, a.id) end end # スキルを返す return skill_array end #-------------------------------------------------------------------------- # ● 蘇生スキルの選定処理 # target : 対象ターゲット # healing_skill : 行動者のスキル #-------------------------------------------------------------------------- def revival_skill_choice(target, healing_skill) # 全体回復優先フラグをオフにする all_recovery = false # HPが減っている対象が2人以上いる場合 if get_healing_battler(healing_skill)[1] != nil then # HP条件をクリアしている場合 if healing_action_ok?(get_healing_battler(healing_skill)[1]) == true then # 全体回復優先フラグをオンにする all_recovery = true end end # 最終命中率を定義 last_skill_hit = 0 # 保存用のスキルIDを定義 save_skill_id = 0 # 所持している回復スキルから検索 (0...healing_skill.size).each do |i| # スキルを取得 skill = healing_skill[i] # 実際のスキル命中率を取得 skill_hit = target.hit_percent(self, skill.id) # 最終命中率よりも値が高い場合 if skill_hit > last_skill_hit then # 最終命中率を更新 last_skill_hit = skill_hit end # 最終命中率よりも50以上値が高い場合 if (skill_hit * 100) / last_skill_hit >= 50 then # スキルが全体蘇生で優先フラグがオンの場合 if skill.scope == 6 and all_recovery == true then # スキルが全体蘇生で戦闘不能者が2人以上いる場合 if $game_party.actors - MINTO.exist_battler >= 2 then # スキルのIDを保存 save_skill_id = skill.id end end # スキルが記憶されていて、そのスキルが全体でない場合 if save_skill_id >= 1 and skill.scope != 6 then # 次の候補へ next end # 回復力を取得 damage = target.attack_damage2(self, skill.id) # 計算上全回復する場合 if target.hp - damage >= target.maxhp then # 全体優先フラグがオンで、最終スキルでない場合 if all_recovery== true and i != healing_skill.size-1 # そのスキルが単体の場合 if skill.scope != 4 then # 次の候補へ next end end # そのスキルを使用(アクションを強制) self.current_action.kind = 1 self.current_action.skill_id = skill.id # 処理を終了 return true # 最終スキルの場合 elsif i == healing_skill.size-1 then # そのスキルを使用(アクションを強制 self.current_action.kind = 1 self.current_action.skill_id = skill.id # 処理を終了 return true else # 次の候補へ next end end end end #-------------------------------------------------------------------------- # ● 回復スキルの選定処理 # target : 対象ターゲット # healing_skill : 行動者のスキル #-------------------------------------------------------------------------- def recovery_skill_choice(target, healing_skill) # スキルを対象に対して威力が高い順にソート healing_skill.sort! do |a, b| target.attack_damage2(self, b.id) <=> target.attack_damage2(self, a.id) end # 全体回復優先フラグをオフにする all_recovery = false # 第2位のバトラーを取得する battler = get_healing_battler(healing_skill)[1] # HPが減っている対象が2人以上いる場合 if battler != nil then # HP条件をクリアしている場合 if healing_action_ok?(battler) == true then # 全体回復優先フラグをオンにする all_recovery = true end end # 最終命中率を定義 last_skill_hit = 0 # 保存用のスキルIDを定義 save_skill_id = 0 # 所持している回復スキルから検索 (0...healing_skill.size).each do |i| # スキルを取得 skill = healing_skill[i] # 実際のスキル命中率を取得 skill_hit = target.hit_percent(self, skill.id) # 最終命中率よりも値が高い場合 if skill_hit > last_skill_hit then # 最終命中率を更新 last_skill_hit = skill_hit end # 最終命中率よりも2/1以上値が高い場合 if (skill_hit * 100) / last_skill_hit >= 50 then # スキルが全体回復で優先フラグがオンの場合 if skill.scope == 4 and all_recovery == true then # スキルのIDを保存 save_skill_id = skill.id end # スキルが記憶されていて、そのスキルが全体でない場合 if save_skill_id >= 1 and skill.scope != 4 then # 次の候補へ next end # 回復力を取得 damage = target.attack_damage2(self, skill.id) # 計算上全回復する場合 if target.hp - damage >= target.maxhp then # 全体優先フラグがオンで、最終スキルでない場合 if all_recovery== true and i != healing_skill.size-1 # そのスキルが単体の場合 if skill.scope != 4 then # 次の候補へ next end end # そのスキルを使用(アクションを強制) self.current_action.kind = 1 self.current_action.skill_id = skill.id # 処理を終了 return true # 最終スキルの場合 elsif i == healing_skill.size-1 then # そのスキルを使用(アクションを強制 self.current_action.kind = 1 self.current_action.skill_id = skill.id # 処理を終了 return true else # 次の候補へ next end end end end #-------------------------------------------------------------------------- # ● 浄化スキルの選定処理 # target : 対象ターゲット # clear_skill : 行動者のスキル #-------------------------------------------------------------------------- def clear_skill_choice(target, clear_skill) # 最終命中率を定義 last_skill_hit = 0 # 最終有効度を定義 last_valid_point = target.state_valid_point # 保存用のスキルIDを定義 save_skill_id = 0 # 所持している浄化スキルから検索 (0...clear_skill.size).each do |i| # スキルを取得 skill = clear_skill[i] # 実際のスキル命中率を取得 skill_hit = target.hit_percent(self, skill.id) # 最終命中率よりも値が高い場合 if skill_hit > last_skill_hit then # 最終命中率を更新 last_skill_hit = skill_hit end # 最終命中率の 2/1 以内に値が収まる場合 if (skill_hit * 100) / last_skill_hit >= 50 then # 1つでも解除可能なステートがある場合 if skill.mute_state?(target.states) == true then # 仮想有効度を取得する valid_point = target.virtual_state_valid_point(skill) # 最終有効度よりも高い場合 if valid_point > last_valid_point then # 最終有効度を更新 last_valid_point = valid_point # スキルのIDを保存 save_skill_id = skill.id end end end end # データを返す return [last_valid_point, save_skill_id] end #-------------------------------------------------------------------------- # ● 援護スキルの選定処理 # target : 対象ターゲット # support_skill : 行動者のスキル # type : 選定タイプ(1 : 有効 -1: 有害) #-------------------------------------------------------------------------- def support_skill_choice(target, support_skill, type) # 最終命中率を定義 last_skill_hit = 0 # もともとの有効度を取得 ori_valid_point = target.state_valid_point # 最終有効度を定義 last_valid_point = target.state_valid_point # 保存用のスキルの配列を作成 save_skill = [] # 所持している援護スキルから検索 (0...support_skill.size).each do |i| # スキルを取得 skill = support_skill[i] # 実際のスキル命中率を取得 skill_hit = target.hit_percent(self, skill.id) # 最終命中率よりも値が高い場合 if skill_hit > last_skill_hit then # 最終命中率を更新 last_skill_hit = skill_hit end # 最終命中率の 2/1 以内に値が収まる場合 if (skill_hit * 100) / last_skill_hit >= 50 then # 仮想有効度を取得する valid_point = target.virtual_state_valid_point(skill) # 選定タイプが有効優先の場合 if type == 1 then # もともとの有効度よりも高い場合 if valid_point > ori_valid_point then # 最終有効度以上の場合 if valid_point >= last_valid_point then # 最終有効度を更新 last_valid_point = valid_point # スキルのIDを保存 save_skill.push(skill.id) end end # 選定タイプが有害優先の場合 else # もともとの有効度よりも低い場合 if valid_point < ori_valid_point then # 最終有効度以下の場合 if valid_point <= last_valid_point then # 最終有効度を更新 last_valid_point = valid_point end # スキルのIDを保存 save_skill.push(skill.id) end end end end # データを返す return [last_valid_point, save_skill] end #-------------------------------------------------------------------------- # ● 回復行動の実行 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def revival_skill_effect(target, skill) # 回復行動の使用判定をクリアした場合 if healing_action_ok?(target) == true then # 使用できる回復スキルを取得 healing_skill = get_healing_skill(target, skill) # 回復効果のスキルがある場合 if healing_skill.size >= 1 then # ターゲットが戦闘不能の場合 if target.dead? == true then # 蘇生スキルを選定 return revival_skill_choice(target, healing_skill) else # 回復スキルを選定 return recovery_skill_choice(target, healing_skill) end end end # 不使用フラグを返す return false end #-------------------------------------------------------------------------- # ● 浄化行動の実行 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def clear_skill_effect(target, skill) # 行動者がアクターの場合 if self.is_a?(Game_Actor) == true then # パーティーを複製する battlers = $game_party.actors.dup # 行動者がエネミーの場合 else # トループを複製する battlers = $game_troop.enemies.dup end # データを定義 data = [0, 0] # 最終有効度を定義 last_valid_point = [] # 保存用のスキルIDを定義 save_skill_id = 0 # バトラーを順番に処理にかける battlers.each do |target| # 対象が戦闘不能の場合 if target.dead? == true # 次の候補ヘ next end # 最終有効度が未設定の場合 if last_valid_point[target.index] == nil then # 有効度を更新 last_valid_point[target.index] = target.state_valid_point end # 使用できる浄化スキルを取得 clear_skill = get_clear_skill(target, skill) # 浄化効果のスキルがある場合 if clear_skill.size >= 1 then # 浄化スキルを選定しデータを取得する data = clear_skill_choice(target, clear_skill) end # 最終有効度よりも高い場合 if data[0] > last_valid_point[target.index] then # 最終有効度を更新 last_valid_point[target.index] = data[0].to_i # スキルのIDを更新 save_skill_id = data[1].to_i # ターゲットを更新 self.target = [target] end end # スキルIDが有効な場合 if save_skill_id >= 1 then # そのスキルを使用(アクションを強制 self.current_action.kind = 1 self.current_action.skill_id = save_skill_id # スキルを取得 skill = Data_Skills_Base.data[save_skill_id] # 有効フラグを返す return true end # 不使用フラグを返す return false end #-------------------------------------------------------------------------- # ● 通常スキルの実行 # target : 対象ターゲット # skill : 行動者のスキル #-------------------------------------------------------------------------- def normal_skill_effect(target, skill) # 通常スキルの使用判定をクリアした場合 if attack_action_ok? == true then # 攻撃スキル、援護スキルのどちらを使うか判定 type = get_attack_action # タイプに応じて分岐 case type[0] # 攻撃 when 1 then # 使用できる攻撃スキルを取得 attack_skill = get_attack_skill(target, skill) # 使用できる攻撃スキルが1つでもある場合 if attack_skill.size >= 1 then # 攻撃スキルの処理を実行 return attack_skill_effect(attack_skill) # 使用できる攻撃スキルがない場合 else # 援護スキルの処理を実行 return support_skill_effect(skill, type[1]) end # 援護 else # 使用できる援護スキルを取得 support_skill = get_support_skill(target, skill) # 使用できる援護スキルが1つでもある場合 if support_skill.size >= 1 then # 援護スキルの処理を実行 return support_skill_effect(skill, type[1]) # 使用できる援護スキルがない場合 else # 攻撃スキルの処理を実行 return attack_skill_effect(get_attack_skill(target, skill)) end end end # 不使用フラグを返す return false end #-------------------------------------------------------------------------- # ● 攻撃スキルの実行 # attack_skill : 行動者のスキル #-------------------------------------------------------------------------- def attack_skill_effect(attack_skill) # 回復フラグを初期化 @ai_type[4] = false # 全体攻撃優先フラグをオフにする all_attack = false # 生存している対象を取得する battler = get_attack_enemy # 攻撃対象を取得する user = battle_target_choice(battler) # 無効な対象の場合 if user.nil? then # メソッドを返す return false end # 対象が2人以上いて、且つ思考タイプが 確実に倒せ 以外の場合 if battler.size >= 2 and @ai_type[2] != "確実に倒せ" then # battler.size * 25 / 2 % の確率をクリアした場合 if battler.size * 25 / 2 > rand(100) or # 又は思考タイプが まとめて攻撃しろ の場合 @ai_type[2] == "まとめて攻撃しろ" then # 全体攻撃優先フラグをオンにする all_attack = true end end # 最終命中率を定義 last_skill_hit = 0 # 保存用のスキルの配列を定義 save_skill = [] # 所持している攻撃スキルから検索 (0...attack_skill.size).each do |i| # スキルを取得 skill = attack_skill[i] # 無効なスキルの場合 if skill.nil? then # 次の候補へ next end # 実際のスキル命中率を取得 skill_hit = user.hit_percent(self, skill.id) # 最終命中率よりも値が高い場合 if skill_hit > last_skill_hit then # 最終命中率を更新 last_skill_hit = skill_hit end # 実際の威力を計算 damage = user.attack_damage2(self, skill.id).to_i # 最終命中率よりも 2/1 以上値が高く、且つダメージが有効な場合 if (skill_hit * 100) / last_skill_hit >= 50 and damage >= 1 then # スキルが全体攻撃で優先フラグがオンの場合 if skill.scope == 2 and all_attack == true then # スキルのIDを保存 save_skill.push(skill.id) end # 全体フラグがオンで、そのスキルが全体でない場合 if all_attack == true and skill.scope != 2 then # 次の候補へ next end # 計算上倒せる場合 if user.hp - damage <= 0 then # そのスキルを使用(アクションを強制) self.current_action.kind = 1 self.current_action.skill_id = skill.id # ターゲットを更新 self.target = [user] # 処理を終了 return true # それ以外のスキルの場合 else # スキルのIDを保存 save_skill.push(skill.id) end end end # 使用候補が1つでもある場合 if save_skill.size >= 1 # 思考タイプが 確実に倒せ の場合 if @ai_type[2] == "確実に倒せ" then # 候補のスキルを並び替える save_skill.sort! do |a, b| # 腕力F A を取得 a_str = Data_Skills_Base.data[a].str_f # 腕力F B を取得 b_str = Data_Skills_Base.data[b].str_f # 対象に対して威力が高い順にソート user.attack_damage2(self, b) * [b_str, 1].max <=> user.attack_damage2(self, a) * [a_str, 1].max end # 候補を3つまでに限定 save_skill = save_skill[0...3] # 無効なスキルを除外 save_skill.compact! end # 無作為にスキルを選定し使用する self.current_action.kind = 1 self.current_action.skill_id = save_skill[rand(save_skill.size)] # ターゲットを更新 self.target = [user] # 処理を終了 return true end # フラグを返す return false end #-------------------------------------------------------------------------- # ● 援護行動の実行 # skill : 行動者のスキル # type : 援護タイプ(1 : 有効 -1: 有害) # try : ループ回数 #-------------------------------------------------------------------------- def support_skill_effect(skill, type = 1, try = 0) # タイプが有効優先の場合 if type == 1 then # 行動者がアクターの場合 if self.is_a?(Game_Actor) == true then # パーティーを複製する battlers = $game_party.actors.dup # 行動者がエネミーの場合 else # トループを複製する battlers = $game_troop.enemies.dup end # 有害優先の場合 else # 行動者がアクターの場合 if self.is_a?(Game_Actor) == true then # ターゲットを思考タイプ別に取得する battlers = [battle_target_choice(get_attack_enemy)] # 行動者がエネミーの場合 else # パーティーを複製する battlers = $game_party.actors.dup end end # データを定義 data = [] # 最高有効度を定義 max_valid_point = [] # 保存用のスキルの配列を定義 save_skill = [] # バトラーを順番に処理にかける battlers.each do |user| # 対象が戦闘不能の場合 if user.dead? == true # 次の候補ヘ next end # 最高有効度を定義 max_valid_point[user.index] = user.state_valid_point # 使用できる援護スキルを取得 support_skill = get_support_skill(user, skill) # 援護効果のスキルがある場合 if support_skill.size >= 1 then # 援護スキルを選定しデータを取得する data[user.index] = support_skill_choice(user, support_skill, type) # 援護可能なスキルがない場合 else # 使用できる攻撃スキルを取得 attack_skill = get_attack_skill(target, skill) # 使用できる攻撃スキルが1つでもある場合 if attack_skill.size >= 1 then # 攻撃スキルを使う return attack_skill_effect(attack_skill) end # 不使用フラグを返す return false end # タイプが有効優先の場合 if type == 1 then # 最高有効度よりも高い場合 if data[user.index][0] > max_valid_point[user.index] then # 最高有効度を更新 max_valid_point[user.index] = data[user.index][0] end # タイプが有害優先の場合 else # 最高有効度よりも低い場合 if data[user.index][0] < max_valid_point[user.index] then # 最高有効度を更新 max_valid_point[user.index] = data[user.index][0] end end end # 対象バトラーを有効度が低い順にソート battlers.sort! do |a, b| a.state_valid_point <=> b.state_valid_point end # バトラーを順番に処理にかける battlers.each do |user| # 対象が戦闘不能の場合 if user.dead? == true # 次の候補ヘ next end # タイプが有効優先の場合 if type == 1 then # 有効度が上昇している場合 if max_valid_point[user.index] > user.state_valid_point then # スキルのIDを更新 save_skill = data[user.index][1] # ターゲットを更新 self.target = [user] # 処理を終了 break end # タイプが有害優先の場合 else # 有効度が低下している場合 if max_valid_point[user.index] < user.state_valid_point then # スキルのIDを更新 save_skill = data[user.index][1] # ターゲットを更新 self.target = [user] # 処理を終了 break end end end # スキルIDが有効な場合 if save_skill.size >= 1 then # 無作為にスキルを選定し使用する self.current_action.kind = 1 self.current_action.skill_id = save_skill[rand(save_skill.size)] # 有効フラグを返す return true end # ループ回数が 0 の場合 if try == 0 then # タイプを逆転してもう一度使う effective = support_skill_effect(skill, type * -1, 1) # 再使用が有効な場合 if effective # 処理を確定 return effective end end # ターゲットを取得 target = battle_target_choice(get_attack_enemy) # 使用できる攻撃スキルを取得 attack_skill = get_attack_skill(target, skill) # 使用できる攻撃スキルが1つでもある場合 if attack_skill.size >= 1 then # 攻撃スキルを使う return attack_skill_effect(attack_skill) end # 不使用フラグを返す return false end end #============================================================================== # ■ Game_Party #------------------------------------------------------------------------------ #  パーティを扱うクラスです。 # ゴールドやアイテムなどの情報が含まれます。 # このクラスのインスタンスは RPG_Party.data で参照されます。 #============================================================================== class Game_Party #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_writer :operation # 作戦 #-------------------------------------------------------------------------- # ● 作戦の取得 #-------------------------------------------------------------------------- def operation @operation ||= [] return @operation end end #============================================================================== # ■ Window_Base #------------------------------------------------------------------------------ #  ゲーム中のすべてのウィンドウのスーパークラスです。 #============================================================================== class Window_Base < Window #-------------------------------------------------------------------------- # ● 縁文字描写 #-------------------------------------------------------------------------- def frame_text(x, y, width, height, text, ag = 0, bitmap = nil) # 予約されたビットマップが存在しない場合 if bitmap == nil then # ウィンドウのビットマップを渡す bitmap = self.contents end # 座標を調節する x = x+1 y = y+1 # 元の色を保存 ori_color = bitmap.font.color.clone # 縁の色を定義 bitmap.font.color.set(0, 0, 0) # 縁文字を描写 bitmap.draw_text(x-1, y, width, height, text, ag) bitmap.draw_text(x+1, y, width, height, text, ag) bitmap.draw_text(x, y-1, width, height, text, ag) bitmap.draw_text(x, y+1, width, height, text, ag) # 元の色に戻す bitmap.font.color = ori_color # 本体の文字を描写 bitmap.draw_text(x, y, width, height, text, ag) end #-------------------------------------------------------------------------- # ● バトラーグラフィックの描画 #-------------------------------------------------------------------------- def draw_battler_graphics(actor, x, y, bitmap = self.contents) # バトラーを読み込む battler = RPG::Cache.battler(actor.battler_name, actor.battler_hue) # バトラーグラフィックを描画 bitmap.blt(x, y, battler, battler.rect) end end #============================================================================== # ■ Window_PartyCommand #------------------------------------------------------------------------------ #  バトル画面で、戦うか逃げるかを選択するウィンドウです。 #============================================================================== class Window_PartyCommand < Window_Selectable #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super(0, 0, 640, 64) self.contents = Bitmap.new(width - 32, height - 32) self.back_opacity = 160 @commands = ["戦う", "逃げる", "作戦"] @item_max = 3 @column_max = 3 draw_item(0, normal_color) draw_item(1, $game_temp.battle_can_escape ? normal_color : disabled_color) draw_item(2, normal_color) self.active = false self.visible = false self.index = 0 end #-------------------------------------------------------------------------- # ● 項目の描画 # index : 項目番号 # color : 文字色 #-------------------------------------------------------------------------- def draw_item(index, color) # カーソルの幅を計算 cursor_width = self.width / @column_max - 32 # カーソルの座標を計算 x = index % @column_max * (cursor_width + 32) self.contents.font.color = color rect = Rect.new(x, 0, cursor_width, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) self.contents.draw_text(rect, @commands[index], 1) end #-------------------------------------------------------------------------- # ● カーソルの矩形更新 #-------------------------------------------------------------------------- def update_cursor_rect # スーパークラスを実行 super end end #============================================================================== # ■ Window_Minto_Command #------------------------------------------------------------------------------ #  一般的なコマンド選択を行うウィンドウです。 #============================================================================== class Window_Minto_Command < Window_Selectable #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :window # 参照するウィンドウ attr_accessor :commands # コマンド #-------------------------------------------------------------------------- # ● オブジェクト初期化 # x : ウィンドウの X 座標 # y : ウィンドウの Y 座標 # width : ウィンドウの幅 # commands : コマンド文字列の配列 #-------------------------------------------------------------------------- def initialize(x, y, width, commands) # コマンドの個数からウィンドウの高さを算出 super(x, y, width, commands.size * 32 + 32) @item_max = commands.size @commands = commands self.contents = Bitmap.new(width - 32, @item_max * 32) self.active = false self.visible = false self.opacity = 0 self.z = 0xffff refresh self.index = 0 end #-------------------------------------------------------------------------- # ● モードチェンジ # mode : モード(0 : ON 1 : OFF) #-------------------------------------------------------------------------- def mode_change(mode = 0) # モードに応じて分岐 case mode # ON の場合 when 0 then # アクティブにする self.active = true # 可視にする self.visible = true # OFF の場合 else # 非アクティブにする self.active = false # 不可視にする self.visible = false end # 更新する update end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh self.contents.clear # 文字サイズを調節 self.contents.font.size = 20 for i in 0...@item_max draw_item(i, normal_color) end end #-------------------------------------------------------------------------- # ● 項目の描画 # index : 項目番号 # color : 文字色 #-------------------------------------------------------------------------- def draw_item(index, color) self.contents.font.color = color rect = Rect.new(4, 32 * index, self.contents.width - 8, 32) self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) self.contents.draw_text(rect, @commands[index]) end #-------------------------------------------------------------------------- # ● 項目の無効化 # index : 項目番号 #-------------------------------------------------------------------------- def disable_item(index) draw_item(index, disabled_color) end #-------------------------------------------------------------------------- # ● カーソルの矩形更新 #-------------------------------------------------------------------------- def update_cursor_rect # カーソル位置が 0 未満かアクティブでない場合 if @index < 0 or not self.active self.cursor_rect.empty return end # 現在の行を取得 row = @index / @column_max # 現在の行が、表示されている先頭の行より前の場合 if row < self.top_row # 現在の行が先頭になるようにスクロール self.top_row = row end # 現在の行が、表示されている最後尾の行より後ろの場合 if row > self.top_row + (self.page_row_max - 1) # 現在の行が最後尾になるようにスクロール self.top_row = row - (self.page_row_max - 1) end # カーソルの幅を計算 cursor_width = self.width / @column_max - 32 # カーソルの座標を計算 x = @index % @column_max * (cursor_width + 32) y = @index / @column_max * 32 - self.oy # カーソルの矩形を更新 self.cursor_rect.set(x, y, cursor_width, 32) end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super # 参照先のウィンドウが無効な場合 if @window == nil # メソッドを終了 return end # X座標を同期させる self.x = @window.index * 144 - @window.ox + 16 end end #============================================================================== # ■ Window_Operation #------------------------------------------------------------------------------ #  作戦画面で、作戦を表示するウィンドウです。 #============================================================================== class Window_Operation < Window_Selectable #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(data = nil) super(16, 352, 608, 64) self.contents = Bitmap.new(width - 32, height - 32) self.z = 0xffff self.active = true self.index = 0 @column_max = 4 @item_max = 4 @command = ["作戦1", "作戦2", "作戦3", "作戦4"] refresh update end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh # ビットマップをクリア self.contents.clear # カラーを通常色に変更 self.contents.font.color = normal_color # @item_max分繰り返す (0...@item_max).each do |i| # カーソルの幅を計算 cursor_width = self.width / @column_max - 32 # カーソルの座標を計算 x = i % @column_max * (cursor_width + 32) # Y座標を取得 y = i / @column_max * 32 # 作戦を描写 draw_operation(x, y, i) end end #-------------------------------------------------------------------------- # ● 作戦の描写 # x : 転送先X座標 # y : 転送先Y座標 # i : インデックス #-------------------------------------------------------------------------- def draw_operation(x, y, i) # カーソルの幅を計算 cursor_width = self.width / @column_max - 32 # 作戦名を描写 frame_text(x, y, cursor_width, 32, @command[i], 1) end end #============================================================================== # ■ Window_Operation_Help #------------------------------------------------------------------------------ #  作戦画面で、解説を表示するウィンドウです。 #============================================================================== class Window_Operation_Help < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super(16, 400, 608, 64) self.contents = Bitmap.new(width - 32, height - 32) self.z = 0xffff end #-------------------------------------------------------------------------- # ● テキスト設定 # text : ウィンドウに表示する文字列 # align : アラインメント (0..左揃え、1..中央揃え、2..右揃え) #-------------------------------------------------------------------------- def set_text(text) return if !text save_text = text.dup + "" text = text.dup + "" # テキストとアラインメントの少なくとも一方が前回と違っている場合 if !MINTO_Bitmap.save_bitmap[text] bitmap = Bitmap.new(self.width - 32, self.height - 32) # テキストを再描画 bitmap.font.color = normal_color width = self.width - 32 # 改行の判定文字 split = " " # テキストデータ設定 data = text @text = text.dup data = data.gsub(/\\[Cc]\[([0-9]+)\]/) { "" } text1 = data.split(/#{split}/)[0].to_s text2 = data.split(/#{split}/)[1].to_s text_width = bitmap.text_size(text1).width text_width1 = bitmap.text_size(text2).width height_p = 1 height_p += 1 if text2 != "" x = (width - text_width) / 2 y = 0 n = 0 @cursor_width = 0 # 表示待ちのメッセージがある場合 if text != "" # 制御文字処理 begin last_text = text.clone text.gsub!(/\\[Vv]\[([0-9]+)\]/) { RPG_Variables::data[$1.to_i] } end until text == last_text text.gsub!(/\\[Nn]\[([0-9]+)\]/) do if RPG_Actors::data[$1.to_i] != nil RPG_Actors::data[$1.to_i].name else "" end end # 便宜上、"\\\\" を "\000" に変換 text.gsub!(/\\\\/) { "\000" } # "\\C" を "\001" に、"\\G" を "\002" に変換 text.gsub!(/\\[Cc]\[([0-9]+)\]/) { "\001[#{$1}]" } text.gsub!(/\\[Gg]/) { "\002" } # c に 1 文字を取得 (文字が取得できなくなるまでループ) while ((c = text.slice!(/./m)) != nil) # \\ の場合 if c == "\000" # 本来の文字に戻す c = "\\" end # \C[n] の場合 if c == "\001" # 文字色を変更 text.sub!(/\[([0-9]+)\]/, "") color = $1.to_i if color >= 0 and color <= 7 bitmap.font.color = text_color(color) end # 次の文字へ next end # 改行文字の場合 if c == " " # y に 1 を加算 y += 32 n += 1 case n when 1 x = ((width - text_width1) / 2) when 2 x = ((width - text_width2) / 2) when 3 x = ((width - text_width3) / 2) when 4 x = ((width - text_width4) / 2) when 5 x = ((width - text_width5) / 2) end # 次の文字へ next end # 文字を描画 bitmap.draw_text(x, y, 40, 32, c, 0) # x に描画した文字の幅を加算 x += bitmap.text_size(c).width end end MINTO_Bitmap.save_bitmap[save_text] = bitmap.dup end self.contents = MINTO_Bitmap.save_bitmap[save_text].dup self.visible = true end end #============================================================================== # ■ Window_Operation_Actors #------------------------------------------------------------------------------ #  作戦画面で、パーティーメンバーを表示するウィンドウです。 #============================================================================== class Window_Operation_Actors < Window_Selectable #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :last_index # 最終インデックス #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(data = nil) super(16, 16, 608, 352) # ビューポートを作成 @view_port = Viewport.new(32, 32, 576, 320) @view_port.z = 0xffff @sprite = Sprite.new(@view_port) @sprite.z = 0x10000 @data = $game_party.actors.clone self.contents = Bitmap.new([@data.size, 1].max * 144, height - 32) @sprite.bitmap = self.contents.dup self.z = 0xffff self.index = 0 self.active = false @column_max = @data.size @item_max = @data.size refresh refresh_base update end #-------------------------------------------------------------------------- # ● 作戦の更新 # index : 作戦のインデックス #-------------------------------------------------------------------------- def update_operation(index) # パティーメンバー分繰り返す (0...@data.size).each do |i| # アクターを取得 actor = @data[i] # 作戦の配列が無効の場合 if $game_party.operation[index] == nil then # ハッシュを作成 $game_party.operation[index] = {} end # 作戦の内容が存在しない場合 if $game_party.operation[index][actor.name] == nil then # 内容を作成 operation = [3, 3, "バランス重視", "弱った敵を狙え"] # 内容を収納する $game_party.operation[index][actor.name] = operation end # AIの思考を更新 actor.ai_type = $game_party.operation[index][actor.name] end # 内容をリフレッシュ refresh end #-------------------------------------------------------------------------- # ● アクターの取得 #-------------------------------------------------------------------------- def actor # アクターを返す return @data[self.index] end #-------------------------------------------------------------------------- # ● X座標の変更 #-------------------------------------------------------------------------- def x=(x) super(x) return if @view_port == nil @view_port.rect.x = self.x+16 end #-------------------------------------------------------------------------- # ● OX座標の変更 #-------------------------------------------------------------------------- def ox=(ox) super(ox) return if @view_port == nil @view_port.ox = self.ox end #-------------------------------------------------------------------------- # ● 解放 #-------------------------------------------------------------------------- def dispose @sprite.bitmap.dispose @sprite.dispose @view_port.dispose super end #-------------------------------------------------------------------------- # ● リフレッシュ_ベース #-------------------------------------------------------------------------- def refresh_base # パティーメンバー分繰り返す (0...@data.size).each do |i| # アクターを取得 actor = @data[i] # X座標を取得 x = i * 144 # Y座標を取得 y = 0 # ステータスの用語を描写 draw_actor_status_base(actor, x, y) end end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh # ビットマップをクリア self.contents.clear # パティーメンバー分繰り返す (0...@data.size).each do |i| # アクターを取得 actor = @data[i] # X座標を取得 x = i * 144 # Y座標を取得 y = 0 # ステータスを描写 draw_actor_status(actor, x, y) end end #-------------------------------------------------------------------------- # ● 名前の描画 # actor : アクター # x : 描画先 X 座標 # y : 描画先 Y 座標 #-------------------------------------------------------------------------- def draw_actor_name(actor, x, y) @sprite.bitmap.font.color = normal_color frame_text(x, y, 120, 32, actor.name, 0, @sprite.bitmap) end #-------------------------------------------------------------------------- # ● 作戦の描写 # actor : 対象アクター # x : 転送先X座標 # y : 転送先Y座標 #-------------------------------------------------------------------------- def draw_actor_operations(actor, x, y) # オート状態の取得 auto = actor.ai == true ? "オート" : "マニュアル" # スキル使用頻度の取得 skill_frequency = actor.ai_type[0].to_s # 回復使用頻度の取得 recovery_frequency = actor.ai_type[1].to_s # 思考モードの取得 main_mode = actor.ai_type[2].to_s # ターゲットモードの取得 target_mode = actor.ai_type[3].to_s # カラーを通常色に変更 self.contents.font.color = normal_color # 文字サイズを調節 self.contents.font.size = 16 # オート状態の描写 self.contents.draw_text(x, 32 * 5, 128, 32, auto, 2) # 思考モードの描写 self.contents.draw_text(x, 32 * 6, 128, 32, main_mode, 2) # ターゲットモードの描写 self.contents.draw_text(x, 32 * 7, 128, 32, target_mode, 2) # 文字サイズを戻す self.contents.font.size = 20 # スキル使用頻度の描写 self.contents.draw_text(x, 32 * 8, 128, 32, skill_frequency, 2) # 回復使用頻度の描写 self.contents.draw_text(x, 32 * 9, 128, 32, recovery_frequency, 2) end #-------------------------------------------------------------------------- # ● 作戦の用語の描写 # x : 転送先X座標 # y : 転送先Y座標 #-------------------------------------------------------------------------- def draw_actor_operations_base(x, y) # 文字サイズを調節 @sprite.bitmap.font.size = 20 # カラーをシステムカラーに変更 @sprite.bitmap.font.color = system_color # 用語 操作 の描写 frame_text(x + 4, 32 * 5, 128, 32, "操作", 0, @sprite.bitmap) # 用語 スキル使用頻度 の描写 frame_text(x + 4, 32 * 8, 128, 32, "攻撃頻度", 0, @sprite.bitmap) # 用語 回復使用頻度 の描写 frame_text(x + 4, 32 * 9, 128, 32, "回復頻度", 0, @sprite.bitmap) end #-------------------------------------------------------------------------- # ● アクターステータスの描写 # actor : 対象アクター # x : 転送先X座標 # y : 転送先Y座標 #-------------------------------------------------------------------------- def draw_actor_status(actor, x, y) # 作戦を描写 draw_actor_operations(actor, x, y) end #-------------------------------------------------------------------------- # ● アクターステータスの基礎の描写 # actor : 対象アクター # x : 転送先X座標 # y : 転送先Y座標 #-------------------------------------------------------------------------- def draw_actor_status_base(actor, x, y) # アクターのグラフィックを描写 draw_battler_graphics(actor, x + 8, y + 32, @sprite.bitmap) # アクターの名前を描写 draw_actor_name(actor, x, y) # 作戦の用語を描写 draw_actor_operations_base(x, y) end #-------------------------------------------------------------------------- # ● 行数の取得 #-------------------------------------------------------------------------- def row_max_width # 項目数と列数から行数を算出 return @item_max end #-------------------------------------------------------------------------- # ● 一行の幅 #-------------------------------------------------------------------------- def row_width return 144 end #-------------------------------------------------------------------------- # ● 先頭の行の取得 #-------------------------------------------------------------------------- def top_row_width # ウィンドウ内容の転送元 Y 座標を、1 行の高さで割る return self.ox / row_width end #-------------------------------------------------------------------------- # ● 先頭の行の設定 # row : 先頭に表示する行 #-------------------------------------------------------------------------- def top_row_width=(row) # row が 0 未満の場合は 0 に修正 if row < 0 row = 0 end # row が row_max - 1 超の場合は row_max - 1 に修正 if row > row_max_width - 1 row = row_max_width - 1 end # row に 1 行の高さを掛け、ウィンドウ内容の転送元 Y 座標とする self.ox = row * row_width end #-------------------------------------------------------------------------- # ● 1 ページに表示できる項目数の取得 #-------------------------------------------------------------------------- def page_item_max_width # 行数 page_row_max に 列数 @column_max を掛ける return page_width_max * @column_max end #-------------------------------------------------------------------------- # ● 1 ページに表示できる幅数の取得 #-------------------------------------------------------------------------- def page_width_max # ウィンドウの幅から、フレームの幅 32 を引き、1 行の高さ 32 で割る return (self.width - 32) / 144 end #-------------------------------------------------------------------------- # ● ウィンドウのスクロール #-------------------------------------------------------------------------- def window_scroll # 現在の行を取得 row = @index # 現在の行が、表示されている先頭の行より前の場合 if row < self.top_row_width # 現在の行が先頭になるようにスクロール self.top_row_width = row end # 現在の行が、表示されている最後尾の行より後ろの場合 if row > self.top_row_width + (self.page_width_max - 1) # 現在の行が最後尾になるようにスクロール self.top_row_width = row - (self.page_width_max - 1) end end #-------------------------------------------------------------------------- # ● カーソルの矩形更新 #-------------------------------------------------------------------------- def update_cursor_rect # カーソル位置が 0 未満の場合 if @index < 0 or not self.active self.cursor_rect.empty return end # ウィンドウのスクロール window_scroll # カーソルの幅を計算 cursor_width = 144 # カーソルの座標を計算 x = @index * 144 - self.ox y = 0 # カーソルの矩形を更新 self.cursor_rect.set(x, y, cursor_width, self.height - 32) end end #============================================================================== # ■ Scene_Menu #------------------------------------------------------------------------------ #  メニュー画面の処理を行うクラスです。 #============================================================================== class Scene_Menu #-------------------------------------------------------------------------- # ● フレーム更新 # alias : update_MINTO_Ai_System #-------------------------------------------------------------------------- alias update_MINTO_Ai_System update def update # 作戦キーが押された場合 if Input.trigger?(MINTO::Operation_Key) # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 作戦画面を実行 Utility_Operation.new return end # 元の処理を実行 update_MINTO_Ai_System end end #============================================================================== # ■ Scene_Battle (分割定義 2) #------------------------------------------------------------------------------ #  バトル画面の処理を行うクラスです。 #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # ● フレーム更新 (パーティコマンドフェーズ) #-------------------------------------------------------------------------- def update_phase2 # C ボタンが押された場合 if Input.trigger?(Input::C) # パーティコマンドウィンドウのカーソル位置で分岐 case @party_command_window.index when 0 # 戦う # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # アクターコマンドフェーズ開始 start_phase3 when 1 # 逃げる # 逃走可能ではない場合 if $game_temp.battle_can_escape == false # ブザー SE を演奏 $game_system.se_play($data_system.buzzer_se) return end # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # 逃走処理 update_phase2_escape when 2 # 作戦 # 決定 SE を演奏 $game_system.se_play($data_system.decision_se) # 作戦画面を実行 Utility_Operation.new return end return end end end #============================================================================== # ■ Scene_Battle (分割定義 3) #------------------------------------------------------------------------------ #  バトル画面の処理を行うクラスです。 #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # ● 次のアクターのコマンド入力へ #-------------------------------------------------------------------------- alias phase3_next_actor_ai phase3_next_actor def phase3_next_actor # アクティブバトラーを記憶 active_battler = @active_battler # 元の処理を実行 phase3_next_actor_ai # KGC[ActiveCountBattle2]が有効な場合 if MINTO.search_kgc("ActiveCountBattle") then # 行動者を設定 @active_battler = active_battler end end #-------------------------------------------------------------------------- # ● 前のアクターのコマンド入力へ #-------------------------------------------------------------------------- def phase3_prior_actor # KGC[ActiveCountBattle2]が有効な場合 if MINTO.search_kgc("ActiveCountBattle") then # メソッドを返す return end # ループ begin # アクターの明滅エフェクト OFF if @active_battler != nil then @active_battler.blink = false end # 最初のアクターの場合 if @actor_index == 0 then # パーティコマンドフェーズ開始 start_phase2 return end # アクターのインデックスを戻す @actor_index -= 1 # アクティブバトラーを更新 @active_battler = $game_party.actors[@actor_index] # 点滅フラグを初期化 @active_battler.blink = true # 2人目以降のアクターがアクターがAIキャラの場合 if @actor_index >= 0 and @active_battler.ai == true then # 点滅フラグを初期化 @active_battler.blink = false # ループ (0...$game_party.actors.size-1).each do |i| # アクターのインデックスを戻す @actor_index -= 1 # 無効なインデックスの場合 if @actor_index <= -1 then # パーティコマンドフェーズ開始 start_phase2 return end # アクティブバトラーを更新 @active_battler = $game_party.actors[@actor_index] # 点滅フラグを有効化 @active_battler.blink = true # アクターがAIキャラでない場合 if @active_battler.ai == false then # ループから抜ける break end end end # アクターがコマンド入力を受け付けない状態ならもう一度 end until @active_battler.inputable? # アクターコマンドウィンドウをセットアップ phase3_setup_command_window end #-------------------------------------------------------------------------- # ● アクターコマンドウィンドウのセットアップ # alias : phase3_setup_command_window_MINTO_Ai_System #-------------------------------------------------------------------------- alias phase3_setup_command_window_MINTO_Ai_System phase3_setup_command_window def phase3_setup_command_window # AIフラグがオンの場合 if @active_battler.ai == true then # AIアクションを起こす @active_battler.ai_action(nil, @active_battler.skills) # ターゲットが予約されている場合 unless @active_battler.target.to_a.empty? then # 有効なターゲットの場合 unless @active_battler.target[0].nil? # ターゲットの位置を取得 index = @active_battler.target[0].index # ターゲットインデックスを予約 @active_battler.current_action.target_index = index # 通常攻撃の場合 if @active_battler.current_action.kind.zero? and @active_battler.current_action.basic.zero? then # 予約されたターゲットをクリア @active_battler.target = [] end end end # 次のアクターへ phase3_next_actor # メソッドを返す return end # 元の処理を実行 phase3_setup_command_window_MINTO_Ai_System end #-------------------------------------------------------------------------- # ● スキルまたはアイテムの対象側バトラー設定 # scope : スキルまたはアイテムの効果範囲 # alias : set_target_battlers_MINTO_Ai_System #-------------------------------------------------------------------------- alias set_target_battlers_MINTO_Ai_System set_target_battlers def set_target_battlers(scope) # ターゲットが予約されている場合 if @active_battler.target.to_a != [] then # 存在フラグをクリア exist = false # ループ処理 for target in @active_battler.target do # ターゲットが存在している場合 if target.exist? == true then # 存在フラグを設定 exist = true end # ループ処理から抜ける break end # 存在フラグが有効な場合 if exist == true then # ターゲットを強制変更する @target_battlers = @active_battler.target.dup # 予約されたターゲットをクリア @active_battler.target = [] # ターゲットを返す return @target_battlers end end # 元の処理を実行 set_target_battlers_MINTO_Ai_System(scope) end #-------------------------------------------------------------------------- # ● フレーム更新 (メインフェーズ ステップ 6 : リフレッシュ) # alias : update_phase4_step6_MINTO_Ai_System #-------------------------------------------------------------------------- alias update_phase4_step6_MINTO_Ai_System update_phase4_step6 def update_phase4_step6 # 元の処理を実行 update_phase4_step6_MINTO_Ai_System # ループ処理 for actor in $game_party.actors do # アクション確定フラグを解除 actor.ai_type[5] = false end end end #============================================================================== # ■ Utility_Operation #------------------------------------------------------------------------------ #  作戦画面の処理を行うクラスです。 #============================================================================== class Utility_Operation < Mint #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize # トランジション準備 Graphics.freeze # メイン処理を実行 main() end #-------------------------------------------------------------------------- # ● メイン処理 #-------------------------------------------------------------------------- def main() # スーパークラスを実行 super() # ダミーコマンドを作成 command = ["", "", "", "", ""] # ダミーコマンドウィンドウを作成 @command_window = Window_Minto_Command.new(16, 176, 162, command) # 思考コマンドを定義 ai_type = [ "回復に専念しろ", "力を温存しろ", "バランス重視", "味方を援護しろ", "敵を妨害しろ", "援護を優先しろ", "妨害を優先しろ", "まとめて倒せ", "確実に倒せ"] # 思考コマンドウィンドウを作成 @ai_type_window = Window_Minto_Command.new(16, 32, 160, ai_type) # Z座標を加算 @ai_type_window.z += 0xfffff # 半透明にする @ai_type_window.opacity = 224 # 優先コマンドを定義 target = [ "弱った敵を狙え", "元気な敵を狙え", "力のある敵を狙え", "硬い敵を狙え", "もろい敵を狙え", "魔防の高い敵を狙え", "魔防の低い敵を狙え", "速い敵を狙え", "遅い敵を狙え"] # 優先タイプウィンドウを作成 @target_window = Window_Minto_Command.new(16, 32, 160, target) # Z座標を加算 @target_window.z += 0xfffff # 半透明にする @target_window.opacity = 224 # 作戦ウィンドウを作成 @operation_window = Window_Operation.new # メンバーウィンドウを作成 @member_window = Window_Operation_Actors.new # 作戦を更新 @member_window.update_operation(@operation_window.index) # メンバーウィンドウを関連付け @command_window.window = @member_window @ai_type_window.window = @member_window @target_window.window = @member_window # ヘルプウィンドウを作成 @help_window = Window_Operation_Help.new # ヘルプテキストを描写 set_help_text("作戦選択") # メインループ main_loop # トランジション準備 Graphics.freeze # ダミーコマンドウィンドウを解放 @command_window.dispose # 思考コマンドウィンドウを解放 @ai_type_window.dispose # 優先タイプウィンドウを解放 @target_window.dispose # 作戦ウィンドウを解放 @operation_window.dispose # メンバーウィンドウを解放 @member_window.dispose # ヘルプウィンドウを解放 @help_window.dispose # トランジション実行 Graphics.transition(20) end #-------------------------------------------------------------------------- # ● モードの変更 # mode : モード #-------------------------------------------------------------------------- def mode_change(mode) # モードフラグに応じて分岐 case mode when "作戦選択" then # 作戦ウィンドウをアクティブにする @operation_window.active = true # 作戦を更新 @member_window.update_operation(@operation_window.index) # メンバーウィンドウを非アクティブにする @member_window.active = false # メンバーウィンドウを更新 @member_window.update when "メンバー選択" then # 作戦ウィンドウを非アクティブにする @operation_window.active = false # 作戦ウィンドウを更新 @operation_window.update # メンバーウィンドウをアクティブにする @member_window.active = true # ダミーコマンドウィンドウのモードを変える @command_window.mode_change(1) when "作戦内容選択" then # メンバーウィンドウを非アクティブにする @member_window.active = false # メンバーウィンドウを更新 @member_window.update # ダミーコマンドウィンドウのモードを変える @command_window.mode_change(0) # 思考コマンドウィンドウのモードを変える @ai_type_window.mode_change(1) # 優先ウィンドウのモードを変える @target_window.mode_change(1) when "思考選択" then # メンバーウィンドウを非アクティブにする @member_window.active = false # メンバーウィンドウを更新 @member_window.update # ダミーコマンドウィンドウのモードを変える @command_window.mode_change(1) # 思考コマンドウィンドウのモードを変える @ai_type_window.mode_change(0) when "優先選択" then # メンバーウィンドウを非アクティブにする @member_window.active = false # メンバーウィンドウを更新 @member_window.update # ダミーコマンドウィンドウのモードを変える @command_window.mode_change(1) # 優先のモードを変える @target_window.mode_change(0) end end #-------------------------------------------------------------------------- # ● ヘルプテキスト設定 # text ヘルプテキスト #-------------------------------------------------------------------------- def set_help_text(text) # テキストに応じて分岐 case text when "作戦選択" then text = "設定したい作戦を選択してください" when "アクター選択" then text = "設定したい対象を選択してください" when "内容選択" then # ダミーコマンドウィンドウのインデックスに応じて分岐 case @command_window.index # 操作選択 when 0 then # アクターの操作モードがマニュアルの場合 if @member_window.actor.ai == false then text = "現在\\c[1]マニュアル\\c[0]モードです" else text = "現在\\c[1]オート\\c[0]モードです" end # 思考選択 when 1 then # 思考ウィンドウの内容に応じて分岐 case @ai_type_window.commands[@ai_type_window.index] when "回復に専念しろ" text = "回復以外のスキルを一切使用しません" when "力を温存しろ" text = "SPが75%以下にならない様にスキルを温存します" when "バランス重視" text = "SPが50%以下にならない程度にバランス良く戦います" when "味方を援護しろ" text = "SPが50%以下にならない程度に味方を援護します" when "敵を妨害しろ" text = "SPが50%以下にならない程度に敵を妨害します" when "援護を優先しろ" text = "SPが25%以下にならない程度に援護を優先します" when "妨害を優先しろ" text = "SPが25%以下にならない程度に妨害を優先します" when "まとめて倒せ" text = "威力よりも、全体攻撃を優先します" when "確実に倒せ" text = "SPを気にせず、強力な攻撃を優先します" end # 優先選択 when 2 then # 優先ウィンドウの内容に応じて分岐 case @target_window.commands[@target_window.index] when "弱った敵を狙え" text = "残りHPの割合が低い敵を優先します" when "元気な敵を狙え" text = "残りHPの割合が高い敵を優先します" when "力のある敵を狙え" text = "攻撃力の高い敵を優先します" when "硬い敵を狙え" text = "防御力の高い敵を優先します" when "もろい敵を狙え" text = "防御力の低い敵を優先します" when "魔防の高い敵を狙え" text = "魔法防御力の高い敵を優先します" when "魔防の低い敵を狙え" text = "魔法防御力の低い敵を優先します" when "速い敵を狙え" text = "素早さの高い敵を優先します" when "遅い敵を狙え" text = "素早さの低い敵を優先します" end # 攻撃頻度設定 when 3 then # アクターの攻撃頻度に応じて分岐 case @member_window.actor.ai_type[0] when 0 text = "一切攻撃を行わず、防御します" when 1 text = "HPが90%以下になると高確率で防御します" when 2 text = "HPが75%以下になると高確率で防御します" when 3 text = "HPが50%以下になると中確率で防御します" when 4 text = "HPが25%以下になると低確率で防御します" when 5 text = "一切防御せず、攻撃を繰り替えします" end # 回復頻度設定 when 4 then # アクターの攻撃頻度に応じて分岐 case @member_window.actor.ai_type[1] when 0 text = "浄化以外の一切回復行動をとりません" when 1 text = "HPが15%以下の味方に回復行動をとります" when 2 text = "HPが35%以下の味方に回復行動をとります" when 3 text = "HPが50%以下の味方に回復行動をとります" when 4 text = "HPが75%以下の味方に回復行動をとります" when 5 text = "HPが99%以下の味方に回復行動をとります" end end end # テキストを描写 @help_window.set_text(text) end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update # スーパークラスを実行 super # 作戦ウィンドウがアクティブの場合 if @operation_window.active == true then # 処理を更新 update_operation # メソッド終了 return end # メンバーウィンドウがアクティブの場合 if @member_window.active == true then # 処理を更新 update_member # メソッド終了 return end # ダミーコマンドウィンドウがアクティブの場合 if @command_window.active == true then # 処理を更新 update_command # メソッド終了 return end # 思考コマンドウィンドウがアクティブの場合 if @ai_type_window.active == true then # 処理を更新 update_ai_type # メソッド終了 return end # 優先ウィンドウがアクティブの場合 if @target_window.active == true then # 処理を更新 update_target # メソッド終了 return end end #-------------------------------------------------------------------------- # ● フレーム更新(作戦ウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_operation # 作戦ウィンドウを更新 @operation_window.update # ヘルプテキストを描写 set_help_text("作戦選択") # 作戦ウィンドウのインデックスが更新されている場合 if @operation_window.index != @last_index then # 作戦を更新 @member_window.update_operation(@operation_window.index) # 最終インデックスを更新 @last_index = @operation_window.index end # C ボタンが押された場合 if Input.trigger?(Input::C) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # モードを変更 mode_change("メンバー選択") # メソッド終了 return end # B ボタンが押された場合 if Input.trigger?(Input::B) == true then # キャンセル SE を演奏 $game_system.se_play(Data_System.data.cancel_se) # 更新フラグを解除 @self_active = false # メソッド終了 return end end #-------------------------------------------------------------------------- # ● フレーム更新(メンバーウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_member # メンバーウィンドウを更新 @member_window.update # ヘルプテキストを描写 set_help_text("アクター選択") # C ボタンが押された場合 if Input.trigger?(Input::C) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # モードを変更 mode_change("作戦内容選択") # メソッド終了 return end # B ボタンが押された場合 if Input.trigger?(Input::B) == true then # キャンセル SE を演奏 $game_system.se_play(Data_System.data.cancel_se) # モードを変更 mode_change("作戦選択") # メソッド終了 return end end #-------------------------------------------------------------------------- # ● フレーム更新(ダミーコマンドウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_command # ダミーコマンドウィンドウを更新 @command_window.update # ヘルプテキストを描写 set_help_text("内容選択") # ダミーコマンドウィンドウの位置に応じて分岐 case @command_window.index # 攻撃頻度切り替え when 3 then # 方向ボタンの右が押された場合 if Input.repeat?(Input::RIGHT) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 攻撃頻度を加算 @member_window.actor.ai_type[0] += 1 # 攻撃頻度がオーバーした場合 if @member_window.actor.ai_type[0] >= 6 then # 攻撃頻度を 0 にする @member_window.actor.ai_type[0] = 0 end # メンバーウィンドウをリフレッシュ @member_window.refresh # メソッドを終了 return end # 方向ボタンの左が押された場合 if Input.repeat?(Input::LEFT) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 攻撃頻度を減算 @member_window.actor.ai_type[0] -= 1 # 攻撃頻度がマイナスになった場合 if @member_window.actor.ai_type[0] <= -1 then # 攻撃頻度を 5 にする @member_window.actor.ai_type[0] = 5 end # メンバーウィンドウをリフレッシュ @member_window.refresh # メソッドを終了 return end # 回復頻度切り替え when 4 # 方向ボタンの右が押された場合 if Input.repeat?(Input::RIGHT) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 回復頻度を加算 @member_window.actor.ai_type[1] += 1 # 回復頻度がオーバーした場合 if @member_window.actor.ai_type[1] >= 6 then # 回復頻度を 0 にする @member_window.actor.ai_type[1] = 0 end # メンバーウィンドウをリフレッシュ @member_window.refresh # メソッドを終了 return end # 方向ボタンの左が押された場合 if Input.repeat?(Input::LEFT) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 回復頻度を減算 @member_window.actor.ai_type[1] -= 1 # 回復頻度がマイナスになった場合 if @member_window.actor.ai_type[1] <= -1 then # 回復頻度を 5 にする @member_window.actor.ai_type[1] = 5 end # メンバーウィンドウをリフレッシュ @member_window.refresh # メソッドを終了 return end end # C ボタンが押された場合 if Input.trigger?(Input::C) == true then # 作戦の変更が許可されていない場合 if @member_window.actor.not_operation == true then # ブザー SE を演奏 $game_system.se_play(Data_System.data.buzzer_se) # メソッドを終了 return end # ダミーコマンドウィンドウの位置に応じて分岐 case @command_window.index # 操作切り替え when 0 then # アクターを取得 actor = @member_window.actor # 操作切り替えが許可されている場合 unless actor.not_control then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # 操作モードを反転させる actor.ai = (actor.ai == false) # メンバーウィンドウをリフレッシュ @member_window.refresh # メソッドを終了 return # 操作が固定の場合 else # ブザー SE を演奏 $game_system.se_play(Data_System.data.buzzer_se) # メソッドを終了 return end # 思考タイプ選択 when 1 then # アクターを取得 actor = @member_window.actor # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # モードを変更 mode_change("思考選択") # メソッドを終了 return # 優先タイプ選択 when 2 then # アクターを取得 actor = @member_window.actor # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # モードを変更 mode_change("優先選択") # メソッドを終了 return end end # B ボタンが押された場合 if Input.trigger?(Input::B) == true then # キャンセル SE を演奏 $game_system.se_play(Data_System.data.cancel_se) # モードを変更 mode_change("メンバー選択") # メソッド終了 return end end #-------------------------------------------------------------------------- # ● フレーム更新(思考コマンドウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_ai_type # 思考コマンドウィンドウを更新 @ai_type_window.update # ヘルプテキストを描写 set_help_text("内容選択") # C ボタンが押された場合 if Input.trigger?(Input::C) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # アクターを取得 actor = @member_window.actor # 思考タイプを変更 actor.ai_type[2] = @ai_type_window.commands[@ai_type_window.index] # メンバーウィンドウをリフレッシュ @member_window.refresh # モードを変更 mode_change("作戦内容選択") # メソッド終了 return end # B ボタンが押された場合 if Input.trigger?(Input::B) == true then # キャンセル SE を演奏 $game_system.se_play(Data_System.data.cancel_se) # モードを変更 mode_change("作戦内容選択") # メソッド終了 return end end #-------------------------------------------------------------------------- # ● フレーム更新(優先コマンドウィンドウがアクティブの場合) #-------------------------------------------------------------------------- def update_target # 優先ウィンドウを更新 @target_window.update # ヘルプテキストを描写 set_help_text("内容選択") # C ボタンが押された場合 if Input.trigger?(Input::C) == true then # 決定 SE を演奏 $game_system.se_play(Data_System.data.decision_se) # アクターを取得 actor = @member_window.actor # 優先タイプを変更 actor.ai_type[3] = @target_window.commands[@target_window.index] # メンバーウィンドウをリフレッシュ @member_window.refresh # モードを変更 mode_change("作戦内容選択") # メソッド終了 return end # B ボタンが押された場合 if Input.trigger?(Input::B) == true then # キャンセル SE を演奏 $game_system.se_play(Data_System.data.cancel_se) # モードを変更 mode_change("作戦内容選択") # メソッド終了 return end end end end