#◆◇◆◇◆ ☆ 多段攻撃β in RTAB ver 1.03 ◇◆◇◆◇ # ☆ マスタースクリプト ver 2.00 以降専用 # 配布元(みんとのお部屋) http://oiuytrewq.hp.infoseek.co.jp/minto.html # サポート掲示板 http://www2.ezbbs.net/21/minto-aaa/ # by みんと # リアルタイム・アクティブバトル(RTAB) Ver 1.16 # 配布元・サポートURL(歯車の城) # http://members.jcom.home.ne.jp/cogwheel/ # by ショウ =begin 更新履歴 ver 1.03 セーブ後にロードできなくなるミスを修正。 ver 1.02 怪しい部分を修正。 ver 1.01 こまごまと修正。 ☆ 動作の確認はRTAB本体と当スクリプトのみで行い、 正常動作を確認しました。 それ以外のスクリプトとの共用は保障しかねます。 説明 RTAB(歯車の城さん)専用の多段攻撃βです。 通常版とは共用できません。 導入箇所はRTABの真下推奨です。 従来の多段攻撃スクリプトとは違い、 多段ヒットの判定をタイミングではなく、攻撃判定で行います。 アニメに攻撃判定を設定することで、 攻撃判定に触れた瞬間にヒットします。 攻撃判定の周りに敵がいれば、その敵も巻き込みます。 攻撃判定の設定はデータベースのアニメーションで行い、 セルのパターンを100以上にしてください。 そのセルが攻撃判定となり、 セルのマスがそのまま攻撃判定の大きさです。 (大体拡大率20が適当) 通常、一度触れた攻撃判定には一度ヒットすると再ヒットしませんが、 攻撃判定セルの「透明度」を変更すると、 攻撃判定がリフレッシュされて再ヒットするようになります。 2ヒット以上させたい場合は適当なところで透明度を変更してください。 また、攻撃判定を設定したアニメには名前に「必ず」 多段 という名前を含ませてください。 設定されていないとうまく行きません。 また、コンティニューでも動作しません。 =end #============================================================================== # ■ Game_Battler (分割定義 1) #------------------------------------------------------------------------------ #  バトラーを扱うクラスです。このクラスは Game_Actor クラスと Game_Enemy クラ # スのスーパークラスとして使用されます。 #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_accessor :cell_hit # 攻撃判定残存フラグ attr_accessor :hit_p # ヒット数 #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- alias initialize_Multi_Attack_β initialize def initialize # 元の処理を実行 initialize_Multi_Attack_β @cell_hit = {} @hit_p = 0 end end #============================================================================== # ■ Game_Actor #------------------------------------------------------------------------------ #  アクターを扱うクラスです。このクラスは Game_Actors クラス ($game_actors) # の内部で使用され、Game_Party クラス ($game_party) からも参照されます。 #============================================================================== class Game_Actor < Game_Battler #-------------------------------------------------------------------------- # ● 通常攻撃の効果適用 # attacker : 攻撃者 (バトラー) # force : 強制実行フラグ #-------------------------------------------------------------------------- def attack_effect(attacker, force = false) # 対象側アニメを取得 anima_id = attacker.animation2_id # 対象側アニメがない場合 if anima_id == 0 then # スーパークラスを実行 return super(attacker) end # アニメーション名を取得 anima_name = Data_Animations.data[anima_id].name # アニメ名に 多段 が含まれない場合 if anima_name.include?("多段") == false then # スーパークラスを実行 return super(attacker) end # 強制実行フラグがオンの場合 if force == true then # スーパークラスを実行 return super(attacker) end # メソッド終了 return false end #-------------------------------------------------------------------------- # ● スキルの効果適用 # user : スキルの使用者 (バトラー) # skill : スキル # force : 強制実行フラグ #-------------------------------------------------------------------------- def skill_effect(user, skill, force = false) # 対象側アニメを取得 anima_id = skill.animation2_id # 対象側アニメがない場合 if anima_id == 0 then # スーパークラスを実行 return super(user, skill) end # アニメーション名を取得 anima_name = Data_Animations.data[anima_id].name # アニメ名に 多段 が含まれない場合 if anima_name.include?("多段") == false then # スーパークラスを実行 return super(user, skill) end # 戦闘中でない場合 if $game_temp.in_battle == false then # スーパークラスを実行 return super(user, skill) end # 強制実行フラグがオンの場合 if force == true then # スーパークラスを実行 return super(user, skill) end # メソッド終了 return false end end #============================================================================== # ■ Game_Enemy #------------------------------------------------------------------------------ #  エネミーを扱うクラスです。このクラスは Game_Troop クラス ($game_troop) の # 内部で使用されます。 #============================================================================== class Game_Enemy < Game_Battler #-------------------------------------------------------------------------- # ● 通常攻撃の効果適用 # attacker : 攻撃者 (バトラー) # force : 強制実行フラグ #-------------------------------------------------------------------------- def attack_effect(attacker, force = false) # 対象側アニメを取得 anima_id = attacker.animation2_id # 対象側アニメがない場合 if anima_id == 0 then # スーパークラスを実行 return super(attacker) end # アニメーション名を取得 anima_name = Data_Animations.data[anima_id].name # アニメ名に 多段 が含まれない場合 if anima_name.include?("多段") == false then # スーパークラスを実行 return super(attacker) end # 強制実行フラグがオンの場合 if force == true then # スーパークラスを実行 return super(attacker) end # メソッド終了 return false end #-------------------------------------------------------------------------- # ● スキルの効果適用 # user : スキルの使用者 (バトラー) # skill : スキル # force : 強制実行フラグ #-------------------------------------------------------------------------- def skill_effect(user, skill, force = false) # 対象側アニメを取得 anima_id = skill.animation2_id # 対象側アニメがない場合 if anima_id == 0 then # スーパークラスを実行 return super(user, skill) end # アニメーション名を取得 anima_name = Data_Animations.data[anima_id].name # アニメ名に 多段 が含まれない場合 if anima_name.include?("多段") == false then # スーパークラスを実行 return super(user, skill) end # 戦闘中でない場合 if $game_temp.in_battle == false then # スーパークラスを実行 return super(user, skill) end # 強制実行フラグがオンの場合 if force == true then # スーパークラスを実行 return super(user, skill) end # メソッド終了 return false end end #============================================================================== # ■ Spriteset_Battle #------------------------------------------------------------------------------ #  バトル画面のスプライトをまとめたクラスです。このクラスは Scene_Battle クラ # スの内部で使用されます。 #============================================================================== class Spriteset_Battle #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :actor_sprites # アクタースプライト attr_reader :enemy_sprites # エネミースプライト end #============================================================================== # ■ Sprite_Battler #------------------------------------------------------------------------------ #  バトラー表示用のスプライトです。Game_Battler クラスのインスタンスを監視し、 # スプライトの状態を自動的に変化させます。 #============================================================================== class Sprite_Battler < RPG::Sprite #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super # バトラーが nil の場合 if @battler == nil self.bitmap = nil loop_animation(nil) return end # ファイル名か色相が現在のものと異なる場合 if @battler.battler_name != @battler_name or @battler.battler_hue != @battler_hue # ビットマップを取得、設定 @battler_name = @battler.battler_name @battler_hue = @battler.battler_hue self.bitmap = RPG::Cache.battler(@battler_name, @battler_hue) @width = bitmap.width @height = bitmap.height self.ox = @width / 2 self.oy = @height if @battler.is_a?(Game_Enemy) @battler.height = @height end # 戦闘不能または隠れ状態なら不透明度を 0 にする if @battler.dead? or @battler.hidden self.opacity = 0 end end # アニメーション ID が現在のものと異なる場合 if @battler.state_animation_id != @state_animation_id @state_animation_id = @battler.state_animation_id loop_animation($data_animations[@state_animation_id]) end # 表示されるべきアクターの場合 if @battler.is_a?(Game_Actor) and @battler_visible # メインフェーズでないときは不透明度をやや下げる if $game_temp.battle_main_phase self.opacity += 3 if self.opacity < 255 else self.opacity -= 3 if self.opacity > 207 end end # 明滅 if @battler.blink blink_on else blink_off end # 不可視の場合 unless @battler_visible # 出現 if not @battler.hidden and not @battler.dead? and (@battler.damage.size < 2 or @battler.damage_pop.size < 2) appear @battler_visible = true end end # ダメージ for battler in @battler.damage_pop if battler[0].class == Array if battler[0][1] >= 0 $scene.skill_se else $scene.levelup_se end damage(@battler.damage[battler[0]], false, 2) else damage(@battler.damage[battler[0]], @battler.critical[battler[0]]) end if @battler.damage_sp.include?(battler[0]) damage(@battler.damage_sp[battler[0]], @battler.critical[battler[0]], 1) @battler.damage_sp.delete(battler[0]) end @battler.damage_pop.delete(battler[0]) @battler.damage.delete(battler[0]) @battler.critical.delete(battler[0]) end # 可視の場合 if @battler_visible # 逃走 if @battler.hidden $game_system.se_play($data_system.escape_se) escape @battler_visible = false end # 白フラッシュ if @battler.white_flash whiten @battler.white_flash = false end # アニメーション unless @battler.animation.empty? for animation in @battler.animation.reverse animation($data_animations[animation[0]], animation[1], animation[2]) @battler.animation.delete(animation) end end # コラプス if @battler.damage.size == 0 and @battler.dead? and @_animation.size == 0 if $scene.dead_ok?(@battler) if @battler.is_a?(Game_Enemy) $game_system.se_play($data_system.enemy_collapse_se) else $game_system.se_play($data_system.actor_collapse_se) end collapse @battler_visible = false end end end # スプライトの座標を設定 self.x = @battler.screen_x self.y = @battler.screen_y self.z = @battler.screen_z if @battler.is_a?(Game_Enemy) self.zoom_x = @battler.real_zoom * @battler.zoom self.zoom_y = @battler.real_zoom * @battler.zoom end end #-------------------------------------------------------------------------- # ● 多段攻撃判定セット # anime : アニメーション #-------------------------------------------------------------------------- def multi_attack_set(anime) # 多段攻撃判定を更新 frame_index = anime[0].frame_max - anime[2] cell_data = anime[0].frames[frame_index].cell_data multi_attack_update(frame_index, cell_data, 0, anime[4]) multi_attack_update(frame_index, cell_data, 1, anime[4]) multi_attack_update(frame_index, cell_data, 2, anime[4]) multi_attack_update(frame_index, cell_data, 3, anime[4]) multi_attack_update(frame_index, cell_data, 4, anime[4]) multi_attack_update(frame_index, cell_data, 5, anime[4]) multi_attack_update(frame_index, cell_data, 6, anime[4]) multi_attack_update(frame_index, cell_data, 7, anime[4]) multi_attack_update(frame_index, cell_data, 8, anime[4]) multi_attack_update(frame_index, cell_data, 9, anime[4]) multi_attack_update(frame_index, cell_data, 10, anime[4]) multi_attack_update(frame_index, cell_data, 11, anime[4]) multi_attack_update(frame_index, cell_data, 12, anime[4]) multi_attack_update(frame_index, cell_data, 13, anime[4]) multi_attack_update(frame_index, cell_data, 14, anime[4]) multi_attack_update(frame_index, cell_data, 15, anime[4]) end #-------------------------------------------------------------------------- # ● 多段攻撃判定更新 # frame_index : 現在のアニメのカウント # cell_data : 実行中のアニメのデータ # i : セルのID # battler : 攻撃の使用者 #-------------------------------------------------------------------------- def multi_attack_update(frame_index, cell_data, i, battler) # 現在のセルのデータが有効の場合 if cell_data[i, 0] != nil then # セルのパターンが 100 以上の場合 if cell_data[i, 0] >= 99 then # 先頭のターゲットに応じて分岐 case battler.target[0] # エネミーの場合 when Game_Enemy then # トループデータを取得 battlers = $game_troop.enemies # エネミースプライトセットを取得 battler_spriteset = $scene.spriteset.enemy_sprites # アクターの場合 when Game_Actor then # パーティーデータを取得 battlers = $game_party.actors # アクタースプライトセットを取得 battler_spriteset = $scene.spriteset.actor_sprites end # 無効なターゲットの場合 if battlers == nil then # メソッドを返す return end # 取得したメンバー分繰り返す (0...battlers.size).each do |id| # ターゲットを取得 target = battlers[id] # 現在のターゲットに応じて分岐 case target # エネミーの場合 when Game_Enemy then # バトラースプライトを取得 sprite = battler_spriteset[battlers.size - (id + 1)] # アクターの場合 when Game_Actor then # バトラースプライトを取得 sprite = battler_spriteset[id] end # ヒット記録データが無効な場合 if target.cell_hit[battler] == nil then # ヒット記録データを作成 target.cell_hit[battler] = {} end # 多段攻撃の判定に成功した場合 if multi_attack_prosper?(cell_data, sprite, target, i, battler) # アクティブバトラーのカレントアクションに応じて分岐 case battler.current_action.kind # 通常攻撃の場合 when 0 then # 通常攻撃の効果を適用 target.attack_effect(battler, true) # スキル攻撃の場合 when 1 then # スキルのIDを取得 skill_id = battler.current_action.skill_id # スキルを取得 skill = Data_Skills_Base.data[skill_id] # スキルの効果を適用 target.skill_effect(battler, skill, true) end # ダメージを表示 sprite.damage(target.damage[battler], target.critical[battler]) # 攻撃の結果を適用 target.damage_effect(battler, battler.current_action.kind) # ダメージの関連データを削除 target.damage_pop.delete(battler) target.damage.delete(battler) target.critical.delete(battler) # 対象がアクターの場合 if target.class == Game_Actor # ステータスウィンドウをリフレッシュ $scene.status_window.refresh end # 今回の攻撃判定のヒット済みフラグをオン target.cell_hit[battler][cell_data[i, 6]] = 1 # ダメージが 1 以上の場合 if target.damage[battler].to_i >= 1 then # ヒット数を加算 target.hit_p += 1 end # ターゲットの配列に存在しない場合 if not battler.target.include?(target) then # ターゲットの配列にプッシュ battler.target.push(target) end end end end end end #-------------------------------------------------------------------------- # ● 攻撃判定の取得 # cell_data : 実行中のアニメのデータ # i : セルのインデックス #-------------------------------------------------------------------------- def get_attack_check(cell_data, i) # セルの現在座標を割り出す cell_x = @battler.screen_x - self.ox + self.src_rect.width / 2 cell_y = @battler.screen_y - self.oy + self.src_rect.height / 2 # セルの座標に、セルの座標修正を加算 cell_x += cell_data[i, 1] cell_y += cell_data[i, 2] # セルの座標に拡大率/2を±した値が攻撃判定となる attack_check = [ cell_x + (cell_data[i, 3] - 20) / 2, cell_x - (cell_data[i, 3] - 20) / 2, cell_y + (cell_data[i, 3] - 20) / 2, cell_y - (cell_data[i, 3] - 20) / 2] # 攻撃判定を返す return attack_check end #-------------------------------------------------------------------------- # ● 当たり判定の取得 # sprite : バトラーのスプライト #-------------------------------------------------------------------------- def get_hit_check(sprite) # ターゲットの座標に画像のサイズ/2を±した値が当たり判定となる hit_check = [ sprite.x - sprite.bitmap.width / 2, sprite.x + sprite.bitmap.width / 2, sprite.y - sprite.bitmap.height / 2, sprite.y + sprite.bitmap.height / 2] # 当たり判定を返す return hit_check end #-------------------------------------------------------------------------- # ● 多段攻撃ヒット判定 # attack_check : 攻撃判定 # hit_check : 当たり判定 #-------------------------------------------------------------------------- def multi_attack_hit?(attack_check, hit_check) # 攻撃判定内に、ターゲットの当たり判定が存在するか判定 attack_check[0] >= hit_check[0] and attack_check[1] <= hit_check[1] and attack_check[2] >= hit_check[2] and attack_check[3] <= hit_check[3] end #-------------------------------------------------------------------------- # ● 多段攻撃成功判定 # cell_data : 実行中のアニメのデータ # sprite : ターゲットのスプライト # target : 現在のターゲット # i : セルのインデックス #-------------------------------------------------------------------------- def multi_attack_prosper?(cell_data, sprite, target, i, battler) # 攻撃判定を取得 attack_check = get_attack_check(cell_data, i) # ターゲットの当たり判定を取得 hit_check = get_hit_check(sprite) # 攻撃判定にターゲットがいる場合 if multi_attack_hit?(attack_check, hit_check) == true then # アクティブバトラーが存在する場合 if battler != nil then # 無効なデータの場合 if target.cell_hit[battler][cell_data[i, 6]] == nil then # データを初期化 target.cell_hit[battler][cell_data[i, 6]] = 0 end # まだ、ヒットしていない場合 if target.cell_hit[battler][cell_data[i, 6]] == 0 then # ターゲットが存在する場合 if target.exist? == true then # フラグを返す return true end end end end # フラグを返す return false end end #============================================================================== # ■ Scene_Battle (分割定義 1) #------------------------------------------------------------------------------ #  バトル画面の処理を行うクラスです。 #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :target_battlers # 通常ターゲットの配列 attr_reader :active_battler # アクティブバトラー attr_reader :spriteset # スプライトセットバトルデータ attr_reader :status_window # ステータスウィンドウ end #============================================================================== # ■ Scene_Battle (分割定義 4) #------------------------------------------------------------------------------ #  バトル画面の処理を行うクラスです。 #============================================================================== class Scene_Battle #-------------------------------------------------------------------------- # ● フレーム更新 (メインフェーズ ステップ 4 : 対象側アニメーション) #-------------------------------------------------------------------------- def update_phase4_step4(battler) # カメラ設定 if battler.target[0].is_a?(Game_Enemy) and battler.anime1 != 0 camera_set(battler) end # 対象側アニメーション for target in battler.target target.animation.push([battler.anime2, (target.damage[battler] != "Miss"), battler]) unless battler.anime2 == 0 battler.wait = 2 * $data_animations[battler.anime2].frame_max - 10 end end # ステップ 5 に移行 battler.phase = 5 end #-------------------------------------------------------------------------- # ● フレーム更新 (メインフェーズ ステップ 6 : リフレッシュ) # alias : update_phase4_step6_Multi_Attack_β #-------------------------------------------------------------------------- alias update_phase4_step6_Multi_Attack_β update_phase4_step6 def update_phase4_step6(battler) # 元の処理を実行 update_phase4_step6_Multi_Attack_β(battler) # ターゲット全員に処理を掛ける for target in battler.target do # ヒット済みフラグを再作成 target.cell_hit = {} end # 極端な処理落ちを防止 Graphics.frame_reset end end #============================================================================== # ■ Spriteモジュール #------------------------------------------------------------------------------ #  アニメーションの管理を行うモジュールです。 #============================================================================== module RPG class Sprite < ::Sprite #------------------------------------------------------------------------ # ● アニメーション作成 # animation : アニメーション # hit : ヒットフラグ( true / false ) # battler : 使用者 #------------------------------------------------------------------------ def animation(animation, hit, battler = nil) return if animation == nil num = @_animation.size @_animation.push([animation, hit, animation.frame_max, [], battler]) bitmap = RPG::Cache.animation(animation.animation_name, animation.animation_hue) if @@_reference_count.include?(bitmap) @@_reference_count[bitmap] += 1 else @@_reference_count[bitmap] = 1 end if @_animation[num][0].position != 3 or not @@_animations.include?(animation) for i in 0..15 sprite = ::Sprite.new sprite.bitmap = bitmap sprite.visible = false @_animation[num][3].push(sprite) end unless @@_animations.include?(animation) @@_animations.push(animation) end end update_animation(@_animation[num]) end #------------------------------------------------------------------------ # ● アニメーション更新 # anime : アニメーション #------------------------------------------------------------------------ def update_animation(anime) # 使用者が存在する場合 if anime[4] != nil and anime[2] > 0 # 多段攻撃判定を更新 multi_attack_set(anime) end if anime[2] > 0 frame_index = anime[0].frame_max - anime[2] cell_data = anime[0].frames[frame_index].cell_data position = anime[0].position animation_set_sprites(anime[3], cell_data, position) for timing in anime[0].timings if timing.frame == frame_index animation_process_timing(timing, anime[1]) end end else @@_reference_count[anime[3][0].bitmap] -= 1 if @@_reference_count[anime[3][0].bitmap] == 0 anime[3][0].bitmap.dispose end for sprite in anime[3] sprite.dispose end @_animation.delete(anime) end end end end