#============================================================================== # ■ ちょっと賢いエネミー Ver0.32                   By むー #------------------------------------------------------------------------------ # 敵の行動をほんのちょっとだけ賢くします。いや、案外間抜けかも知れませんが…。 #------------------------------------------------------------------------------ # # ★簡単な仕様★ # #  本来、データベースでエネミーの行動を指定する際の条件は、 #  そのエネミーがどのような状態か、です。 #  HP20%〜60%などのように指定すると、そのエネミーのHPを参考にします。 #  このスクリプトでは、それを敵の味方(Troop)全体で判断します。 #  HP20%〜60%などのように指定すると、敵グループの中で該当者がいないかを探し、 #  いればその行動を、その該当者に対しておこなうようになります。 #  ただし、その行動の計算はターンの最初でおこなうため、実行は次のターンです。 # # ★条件★ # #  HP、MP、ステートのみ有効です。 #  ターン、パーティレベル、スイッチは、やや賢い行動の元になりません。 # # ★設定方法★ # #  少しだけ賢い行動をさせたい行動の優先度(Rate)を10にしてください。 #  優先行動が複数当てはまった場合、行動はランダムとなります。 # # ★行動の仕様★ # #  例: スライム #    データベースの行動設定 #    [攻撃     条件:常時    優先度 5] #    [レイズ    条件:ステート1  優先度10] #    [ヒール    条件:HP20%〜60% 優先度10] #    [マナドレイン 条件:MP 0%〜90% 優先度10] # #  ・自分も含め仲間に常時以外の条件がない場合 #    →常時の行動のみ #  ・自分を含めHPの割合30%が1匹の場合 #    →その1匹にヒール #  ・自分を含めHPの割合30%ちょうどが3匹の場合 #    →3匹のうちいずれかにヒール(ランダム) #  ・自分を含めHPの割合30%、40%、50%の3匹がいる場合 #    →最も割合の低い30%の味方にヒール #     (同条件でヒールを使う者が複数いる場合全員同じターゲット) #  ・戦闘不能の仲間が1匹いる場合 #    →その1匹にレイズ #  ・戦闘不能の仲間が3匹いる場合 #    →その3匹のうちいずれかにレイズ(使用者は全員ランダム) #  ・自分を含めHPの割合30%が1匹と戦闘不能の仲間が1匹いる場合 #    →ヒールまたはレイズをランダムで該当ターゲットへおこなう #  ・自分を含めMPの割合が50%の仲間がいる #    →マナドレイン(自分のMPが回復) # #  ・設定項目CRV_ACTがtrueの場合 #    →優先度10の行動いずれかを必ずおこなう(MP/TPにより使用可能な場合) #  ・設定項目CRV_ACTがfalseの場合 #    →行動設定の中からランダムで選択される(MP/TPにより使用可能な場合) # #============================================================================== module MOO_ENEMY_CLEVER_ACTION #-------------------------------------------------------------------------- # 以下、設定箇所です。 #-------------------------------------------------------------------------- # 行動条件に合致した時に必ずその行動をするか(うまく動作するか不明) CRV_ACT = true # ・行動条件→HPの割合/MPの割合/ステートの付加が条件に合致しているか # ・使用条件→スキルを使うためのMP/TPが足りているか # 行動条件と使用条件が真の場合、対象に指定した行動をおこないます。 # その時、必ずその行動を起こす場合はtrue、 # 全行動の中からランダムの場合はfalseを指定します。 # デバッグ表示 ACT_DEBUG = true # 開発中、実際に動きを見たい場合はtrueにしてください。 #-------------------------------------------------------------------------- # ここまで。 #-------------------------------------------------------------------------- # 本スクリプトを使用する(変更しないでください) ACT_USE = true # falseにすると本スクリプトの機能は使わなくなり、 # 再定義メソッドは再定義していない初期状態と同じになります。 # 強制する行動のレート(変更しないでください) ACT_RATE = 10 end #============================================================================== # ■ Game_Action #------------------------------------------------------------------------------ #  戦闘行動を扱うクラスです。このクラスは Game_Battler クラスの内部で使用され # ます。 #============================================================================== class Game_Action #-------------------------------------------------------------------------- # ● 敵キャラの戦闘行動を設定 <再定義> # action : RPG::Enemy::Action #-------------------------------------------------------------------------- def set_enemy_action(action) if action # エラー回避(行動を何も拾ってこなかった場合?) begin set_skill(action.skill_id) rescue set_skill(1) end else clear end end #-------------------------------------------------------------------------- # ● 味方に対するターゲット <再定義> #-------------------------------------------------------------------------- def targets_for_friends if item.for_user? [subject] elsif item.for_dead_friend? if item.for_one? if MOO_ENEMY_CLEVER_ACTION::ACT_USE # ・・・・・・・・・・・・・・・・・・・・・・・・・・・↓ # ターゲットが指定されている場合は固定ターゲット return [$game_troop.members[$moo_troop_target_id_st]] if $moo_troop_target_id_st > -1 [friends_unit.smooth_dead_target(@target_index)] else [friends_unit.smooth_dead_target(@target_index)] end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ else friends_unit.dead_members end elsif item.for_friend? if item.for_one? if MOO_ENEMY_CLEVER_ACTION::ACT_USE # ・・・・・・・・・・・・・・・・・・・・・・・・・・・↓ # ターゲットが指定されている場合は固定ターゲット return [$game_troop.members[$moo_troop_target_id_st]] if $moo_troop_target_id_st > -1 return [$game_troop.members[$moo_troop_target_id_hp]] if $moo_troop_target_id_hp > -1 return [$game_troop.members[$moo_troop_target_id_mp]] if $moo_troop_target_id_mp > -1 # [friends_unit.smooth_target(@target_index)] else [friends_unit.smooth_target(@target_index)] end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ else friends_unit.alive_members end end end end #============================================================================== # ■ Game_BattlerBase #------------------------------------------------------------------------------ #  バトラーを扱う基本のクラスです。主に能力値計算のメソッドを含んでいます。こ # のクラスは Game_Battler クラスのスーパークラスとして使用されます。 #============================================================================== class Game_BattlerBase #-------------------------------------------------------------------------- # ○ HP の割合を取得 <新規> #-------------------------------------------------------------------------- def hp_rate2(param1, param2) # エネミーの行動の場合 if enemy? # 変数初期化 a = 0 b = -1 c = 1.to_f $moo_troop_target_id_hp = -1 hpr = [] # 敵グループのループ for en in $game_troop.members # HPが0かそれ以外か if en.hp.to_f == 0 # HPが0の場合は計算対象にしない hpr[a] = 1.to_f else # 割合計算 mhp_int = en.hp.to_f / en.mhp # 使用条件を下回る値だった場合は対象にしない mhp_int = 1.to_f if mhp_int < param1 # 配列に代入 hpr[a] = mhp_int # 割合が以前より下回る場合はその配列番号を保持(戦闘不能は除く) b = a if c > hpr[a] and hpr[a] != 0 end # 配列用カウントアップ a += 1 end # 割合最小値のグループインデックスをグローバル変数化(ターゲットIDとなる) $moo_troop_target_id_hp = b # 値を返す return hpr.min else # アクターの行動の場合は通常通り hp_rate end end #-------------------------------------------------------------------------- # ○ MP の割合を取得 <新規> #-------------------------------------------------------------------------- def mp_rate2(param1, param2) # 変数初期化 $moo_troop_target_id_mp = -1 # 最大MPが0の場合は0を返す return 0 if mmp == 0 # エネミーの行動の場合 if enemy? # 変数初期化 a = 0 b = -1 c = 1.to_f mpr = [] # 敵グループのループ for en in $game_troop.members # MPが0かそれ以外か if en.mp.to_f == 0 or en.mmp == 0 # 対象外とする mpr[a] = 1.to_f else # 割合計算 mmp_int = en.mp.to_f / en.mmp # 使用条件を下回る値だった場合は対象にしない mmp_int = 1.to_f if mmp_int < param1 # 配列に代入 mpr[a] = mmp_int end # 割合が以前より下回る場合はその配列番号を保持 b = a if c > mpr[a] # 配列用カウントアップ a += 1 end # 割合最小値のグループインデックスをグローバル変数化ターゲットIDとなる) $moo_troop_target_id_mp = b # 値を返す return mpr.min else # アクターの行動の場合は通常通り mp_rate end end end #============================================================================== # ■ Game_Enemy #------------------------------------------------------------------------------ #  敵キャラを扱うクラスです。このクラスは Game_Troop クラス($game_troop)の # 内部で使用されます。 #============================================================================== class Game_Enemy < Game_Battler #-------------------------------------------------------------------------- # ◎ 行動条件合致判定[HP] <エイリアス> #-------------------------------------------------------------------------- alias moo_enemy_clever_action_conditions_met_hp? conditions_met_hp? def conditions_met_hp?(param1, param2) if MOO_ENEMY_CLEVER_ACTION::ACT_USE hp_rate2(param1, param2) >= param1 && hp_rate2(param1, param2) <= param2 else moo_enemy_clever_action_conditions_met_hp?(param1, param2) end end #-------------------------------------------------------------------------- # ◎ 行動条件合致判定[MP] <エイリアス> #-------------------------------------------------------------------------- alias moo_enemy_clever_action_conditions_met_mp? conditions_met_mp? def conditions_met_mp?(param1, param2) if MOO_ENEMY_CLEVER_ACTION::ACT_USE mp_rate2(param1, param2) >= param1 && mp_rate2(param1, param2) <= param2 else moo_enemy_clever_action_conditions_met_mp?(param1, param2) end end #-------------------------------------------------------------------------- # ◎ 行動条件合致判定[ステート] <エイリアス> #-------------------------------------------------------------------------- alias moo_enemy_clever_action_conditions_met_state? conditions_met_state? def conditions_met_state?(param1, param2) if MOO_ENEMY_CLEVER_ACTION::ACT_USE # 変数初期化 a = 0 b = 0 flg = false $moo_troop_target_id_st = -1 str = [] # 敵グループのループ for en in $game_troop.members # 配列の内容の初期値 str[a] = 0 # 該当ステートが付加していた場合 if en.state?(param1) # 配列にステートID str[a] = param1 # 対象数カウント b += 1 end # 配列用カウントアップ a += 1 end # 変数初期化 a = 0 # ステートが付加しているエネミー数によって分岐 if b == 0 # いない場合はfalse flg = false elsif b >= 1 # 2匹以上の場合はランダム a = rand(b) + 1 else # 1匹の場合は1 a = 1 end # 変数初期化 b = 1 # ステート付加配列分ループ for i in 0...str.size # 指定ステートが付加されており配列順が該当する場合 if str[i] == param1 and a == b # ターゲットIDを指定 $moo_troop_target_id_st = i # trueを返す flg = true break end b += 1 if str[i] == param1 end return flg else moo_enemy_clever_action_conditions_met_state?(param1, param2) end end #-------------------------------------------------------------------------- # ◎ 現在の状況で戦闘行動が有効か否かを判定 <エイリアス> # action : RPG::Enemy::Action #-------------------------------------------------------------------------- alias moo_enemy_clever_action_action_valid? action_valid? def action_valid?(action) if MOO_ENEMY_CLEVER_ACTION::ACT_USE $act_id_st = -1 if $act_id_st == nil return action_valid2?(action) else moo_enemy_clever_action_action_valid?(action) end end #-------------------------------------------------------------------------- # ○ 現在の状況で戦闘行動が有効か否かを判定(追加) <新規> # action : RPG::Enemy::Action #-------------------------------------------------------------------------- def action_valid2?(action) cm = conditions_met?(action) $moo_troop_target_id_st = -1 if $moo_troop_target_id_st == nil $act_id_st = action.skill_id if cm and $moo_troop_target_id_st > -1 return cm && usable?($data_skills[action.skill_id]) end #-------------------------------------------------------------------------- # ● 戦闘行動をランダムに選択 <再定義> # action_list : RPG::Enemy::Action の配列 # rating_zero : ゼロとみなすレーティング値 #-------------------------------------------------------------------------- def select_enemy_action(action_list, rating_zero) sum = action_list.inject(0) {|r, a| r += a.rating - rating_zero } return nil if sum <= 0 value = rand(sum) if MOO_ENEMY_CLEVER_ACTION::ACT_USE # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↓ crv_rate = MOO_ENEMY_CLEVER_ACTION::ACT_RATE # 条件に一致した場合その行動しか取れないようにするか $moo_troop_target_id_st = -1 if $moo_troop_target_id_st == nil $moo_troop_target_id_hp = -1 if $moo_troop_target_id_hp == nil $moo_troop_target_id_mp = -1 if $moo_troop_target_id_mp == nil if MOO_ENEMY_CLEVER_ACTION::CRV_ACT if $moo_troop_target_id_st > -1 or $moo_troop_target_id_hp > -1 or $moo_troop_target_id_mp > -1 al = [] for a in action_list al << a if a.rating == crv_rate end action_list = al if al.size > 0 end end # 配列をランダム化する事で強制行動の順番をランダムにする action_list = action_list.sort_by{rand} end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ action_list.each do |action| if MOO_ENEMY_CLEVER_ACTION::ACT_USE # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↓ # 行動の固定化 # ステートが条件の場合 if $moo_troop_target_id_st > -1 and action.rating == crv_rate and action.skill_id == $act_id_st and action.condition_type == 4 # 使用するスキルの対象が味方の場合 if $data_skills[action.skill_id].scope >= 7 # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(スキル条件: 味方)" p "   " + $data_skills[action.skill_id].name + "/予測 → " + $moo_troop_target_id_st.to_s end # アクションを固定する return action # 使用するスキルの対象が相手の場合 else # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(スキル条件: 相手)" p "   " + $data_skills[action.skill_id].name + " → ランダム" end # 対象はランダムにするようグローバル変数に代入 $moo_troop_target_id_hp = -1 $moo_troop_target_id_mp = -1 # アクションを固定する return action end end # HPが条件の場合 if $moo_troop_target_id_hp > -1 and action.rating == crv_rate and action.condition_type == 2 # 使用するスキルの対象が味方の場合 if $data_skills[action.skill_id].scope >= 7 # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(HP条件: 味方)" p "   " + $data_skills[action.skill_id].name + "/予測 → " + $moo_troop_target_id_hp.to_s end # アクションを固定する return action # 使用するスキルの対象が相手の場合 else # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(HP条件: 相手)" p "   " + $data_skills[action.skill_id].name + " → ランダム" end # 対象はランダムにするようグローバル変数に代入 $moo_troop_target_id_st = -1 $moo_troop_target_id_mp = -1 # アクションを固定する return action end end # MPが条件の場合 if $moo_troop_target_id_mp > -1 and action.rating == crv_rate and action.condition_type == 3 # 使用するスキルの対象が味方の場合 if $data_skills[action.skill_id].scope >= 7 # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(MP条件: 味方)" p "   " + $data_skills[action.skill_id].name + "/予測 → " + $moo_troop_target_id_mp.to_s end # アクションを固定する return action # 使用するスキルの対象が相手の場合 else # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(MP条件: 相手)" p "   " + $data_skills[action.skill_id].name + " → ランダム" end # 対象はランダムにするようグローバル変数に代入 $moo_troop_target_id_st = -1 $moo_troop_target_id_hp = -1 # アクションを固定する return action end end end if value < action.rating - rating_zero # デバッグモード if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p " ・実際に使うスキル(固定条件なし: ランダム)" p "   " + $data_skills[action.skill_id].name + " → ランダム" end return action end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ # return action if value < action.rating - rating_zero value -= action.rating - rating_zero end end #-------------------------------------------------------------------------- # ● 戦闘行動の作成 <再定義> #-------------------------------------------------------------------------- def make_actions $act_id_st = -1 super return if @actions.empty? action_list = enemy.actions.select {|a| action_valid?(a) } # デバッグモード ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↓ if MOO_ENEMY_CLEVER_ACTION::ACT_DEBUG p "------------------------------" p "[" + enemy.name + "]" p " ・使用可能スキル" for i in action_list p "   " + $data_skills[i.skill_id].name end end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ return if action_list.empty? rating_max = action_list.collect {|a| a.rating }.max rating_zero = rating_max - 3 # ちょっと賢い行動予定の場合はゼロレートをなくす ・・・・・・・・・・・・・・・・・・・・↓ if MOO_ENEMY_CLEVER_ACTION::ACT_USE $moo_troop_target_id_st = -1 if $moo_troop_target_id_st == nil $moo_troop_target_id_hp = -1 if $moo_troop_target_id_hp == nil $moo_troop_target_id_mp = -1 if $moo_troop_target_id_mp == nil if $moo_troop_target_id_st > -1 or $moo_troop_target_id_hp > -1 or $moo_troop_target_id_mp > -1 rating_zero = 0 end end # ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・↑ action_list.reject! {|a| a.rating <= rating_zero } @actions.each do |action| action.set_enemy_action(select_enemy_action(action_list, rating_zero)) end end end