#============================================================================== # ■ XP-RGSS-3 ステート表示拡張 [Ver.1.0.2] by Claimh #------------------------------------------------------------------------------ # ・ステートのアニメーション表示を多重化します。(順々に切り替え) # ・バトラー下にステートを表示させます。 #-< 再定義箇所 >--------------------------------------------------------------- # Sprite_Battlerクラスの全メソッド(initialize, dispose, update) #============================================================================== module State_Extension #============================================================================== # カスタマイズSTART #============================================================================== #-------------------------------------------------------------------------- # ◆ ステートアニメーション設定 #-------------------------------------------------------------------------- # アニメーション表示のローテーション機能を有効にする? # ステートアニメーションを順繰りに変えます。 # (例)ステートA ⇒ ステートB ⇒ ステートC ⇒ ステートA ・・・ STATE_ANIME = true # true:有効 false:無効 # アニメーションループ回数 LOOP_COUNT = 4 #-------------------------------------------------------------------------- # ◆ ステート表示設定 #-------------------------------------------------------------------------- # アクター下にステート表示をする? # true:表示 false:非表示 ACTOR_STATE = true # エネミー下にステート表示をする? # true:表示 false:非表示 ENEMY_STATE = true # ステートの表示方法パターン # 0:通常表示(表示ができるステート数に限りができます) # 1:ローテーション表示(いくつかのステートを順繰りに表示) # 2:ステートアニメーションと同期(表示中のアニメと同じステートを表示) # ※アニメーションのないステートは表示されません。 STATE_PATTERN = 1 # 表示位置補正(y軸方向) STATE_Y = 4 #-------------------------------------------------------------------------- # ◆ ローテーション設定 :STATE_PATTARN = 1 のときのみ有効 #-------------------------------------------------------------------------- # ローテーションの更新をするフレーム数 ROT_COUNT = 40 #-------------------------------------------------------------------------- # ◆ ステートのアイコン表示設定 #-------------------------------------------------------------------------- # 戦闘中のステートをアイコン表示にする? # true:アイコン表示 false:テキスト表示(処理重い) STATE_ICON = true # メニューのステートをアイコン表示する? MENU_ST_ICON = true # 各ステートのアイコン指定 # ※ アイコン指定のないステートは表示されなくなります STATE_ICON_FILE = { # ステートID => "アイコンファイル名" 1 => "044-Skill01", 3 => "045-Skill02", 4 => "046-Skill03", 5 => "046-Skill03", 6 => "049-Skill06", 7 => "050-Skill07", 8 => "050-Skill07" } # アイコンの表示間隔 ICON_INTERVAL = 5 #============================================================================== # カスタマイズEND #============================================================================== module_function #-------------------------------------------------------------------------- # ● ステートのアニメーション ID 取得 #-------------------------------------------------------------------------- def state_animations(states) # ステートがひとつも付加されていない場合 if states.size == 0 return [] end animations = [] for i in 0...states.size animations.push($data_states[states[i]].animation_id) end # アニメーションID = 0を削除 animations.delete(0) # 全てのアニメーションIDを返す return animations end #-------------------------------------------------------------------------- # ● 描画用のステート文字列作成 # state : ステートID群 # width : 描画先の幅 #-------------------------------------------------------------------------- def make_state_text(bitmap, state, width) # 括弧の幅を取得 brackets_width = bitmap.text_size("[]").width # ステート名の文字列を作成 text = "" for i in state if $data_states[i].rating >= 1 if text == "" text = $data_states[i].name else new_text = text + "/" + $data_states[i].name text_width = bitmap.text_size(new_text).width if text_width > width - brackets_width break end text = new_text end end end # ステート名の文字列が空? if text != "" # 括弧をつける text = "[" + text + "]" end # 完成した文字列を返す return text end #-------------------------------------------------------------------------- # ● 描画用のステートアイコン群作成 # state : ステートID群 # width : 描画先の幅 #-------------------------------------------------------------------------- def make_state_icon(state, width) icon_width = 0 icon_states = [] for i in 0...state.size unless STATE_ICON_FILE[state[i]].nil? # アイコンファイルのビットマップ読み込み bitmap = RPG::Cache.icon(STATE_ICON_FILE[state[i]]) next_width = icon_width + bitmap.width + ICON_INTERVAL # 表示範囲をオーバーしていないか? if width > next_width # 表示アイコンに追加 icon_states.push(STATE_ICON_FILE[state[i]]) # 幅更新 icon_width += bitmap.width + ICON_INTERVAL else break end end end return icon_states end #-------------------------------------------------------------------------- # ● ローテーションさせるかの判定 # state : ステートID群 # width : 描画先の幅 #-------------------------------------------------------------------------- def do_rotation?(bitmap, state, width) case STATE_ICON when true # アイコン icon_width = 0 for i in 0...state.size unless STATE_ICON_FILE[state[i]].nil? # アイコンファイルのビットマップ読み込み bitmap = RPG::Cache.icon(STATE_ICON_FILE[state[i]]) next_width = icon_width + bitmap.width + ICON_INTERVAL # 表示範囲をオーバーしていないか? if width > next_width # 幅更新 icon_width += bitmap.width + ICON_INTERVAL else # ローテーションが必要 return true end end end when false # テキスト # 括弧の幅を取得 brackets_width = bitmap.text_size("[]").width # ステート名の文字列を作成 text = "" for i in state if $data_states[i].rating >= 1 if text == "" text = $data_states[i].name else new_text = text + "/" + $data_states[i].name text_width = bitmap.text_size(new_text).width if text_width > width - brackets_width # ローテーションが必要 return true end text = new_text end end end else p "Err:STATE_ICON" exit end # ローテーションは不要 return false end #-------------------------------------------------------------------------- # ● ステートのローテーション # state : ステートID群 # index : ローテーション開始Index #-------------------------------------------------------------------------- def rotation_state(state, index) rot_state = [] for i in index...state.size rot_state.push(state[i]) end for i in 0...index rot_state.push(state[i]) end return rot_state end #-------------------------------------------------------------------------- # ● ステート用アイコンの描画開始位置の計算 # state : ステートID群 # width : 描画先の幅 #-------------------------------------------------------------------------- def make_icon_pos_x(state, width) icon_width = 0 for i in 0...state.size bitmap = RPG::Cache.icon(state[i]) # 幅更新 icon_width += bitmap.width + ICON_INTERVAL end # 描画開始位置の計算 pos_x = (width - icon_width) / 2 return pos_x end end #============================================================================== # ■ Sprite_Battler #============================================================================== class Sprite_Battler < RPG::Sprite # ステート表示領域の幅、高さを定義 BITMAP_WIDTH = 120 BITMAP_HEIGHT = 32 #-------------------------------------------------------------------------- # ● オブジェクト初期化 [再定義] # viewport : ビューポート # battler : バトラー (Game_Battler) #-------------------------------------------------------------------------- def initialize(viewport, battler = nil) super(viewport) @battler = battler @battler_visible = false #-[ステート表示拡張]------ @rotation_count = 0 # ローテーション用のカウント @rotation_index = 0 # ローテーションIndex @loop_state_animation_count = 0 # ループカウント @battler_state = [] # 内部保持用ステート @state_update_flag = false # ステート更新フラグ @sync_update_flag = false # アニメーション同期用フラグ # ステート表示用スプライトを用意 @state_sprite = Sprite.new(viewport) @state_sprite.bitmap = Bitmap.new(BITMAP_WIDTH, BITMAP_HEIGHT) #------------------------- end #-------------------------------------------------------------------------- # ● 解放 [再定義] #-------------------------------------------------------------------------- def dispose #-[ステート表示拡張]------ @state_sprite.dispose #------------------------- if self.bitmap != nil self.bitmap.dispose end super end #-------------------------------------------------------------------------- # ● フレーム更新 [再定義] #-------------------------------------------------------------------------- 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 # 戦闘不能または隠れ状態なら不透明度を 0 にする if @battler.dead? or @battler.hidden self.opacity = 0 end end #-[ステート表示拡張]------ =begin ↓原型↓ # アニメーション ID が現在のものと異なる場合 if @battler.damage == nil and @battler.state_animation_id != @state_animation_id @state_animation_id = @battler.state_animation_id loop_animation($data_animations[@state_animation_id]) end ↑原型↑ =end # ステート拡張表示 update_state_extension #------------------------- # 表示されるべきアクターの場合 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 == nil or @battler.damage_pop) appear @battler_visible = true end 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 # アニメーション if @battler.animation_id != 0 animation = $data_animations[@battler.animation_id] animation(animation, @battler.animation_hit) @battler.animation_id = 0 end # ダメージ if @battler.damage_pop damage(@battler.damage, @battler.critical) @battler.damage = nil @battler.critical = false @battler.damage_pop = false end # コラプス if @battler.damage == nil and @battler.dead? 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 # スプライトの座標を設定 self.x = @battler.screen_x self.y = @battler.screen_y self.z = @battler.screen_z end #============================================================================== # ■ 拡張メソッド #============================================================================== #-------------------------------------------------------------------------- # ● ステート拡張表示の更新 #-------------------------------------------------------------------------- def update_state_extension unless @battler_visible if @battler.is_a?(Game_Enemy) @state_sprite.bitmap.clear return end end # ステートが更新された? if @battler.damage == nil if @battler_state != @battler.states @battler_state = @battler.states.dup # ステートの更新 @state_update_flag = true # 更新フラグON end end # ステートアニメーションの更新 update_state_animation # ステート表示の更新 update_state # 更新の終了 @state_update_flag = false # ステート更新フラグOFF @sync_update_flag = false # ステートアニメーションの更新フラグOFF end #-------------------------------------------------------------------------- # ● ステートアニメーション更新 #-------------------------------------------------------------------------- def update_state_animation # ステートアニメーション if State_Extension::STATE_ANIME # 多重ステートアニメーションを表示する multiple_state_animation else # 通常の表示方法を選択 # アニメーション ID が現在のものと異なる場合 [原型を使用する] if @battler.damage == nil and @battler.state_animation_id != @state_animation_id @state_animation_id = @battler.state_animation_id loop_animation($data_animations[@state_animation_id]) end end end #-------------------------------------------------------------------------- # ● 多重ステートアニメーション #-------------------------------------------------------------------------- def multiple_state_animation # アニメーションのあるステートを読み込み anime_states = State_Extension.state_animations(@battler_state) # アニメーションのあるステートが付与されている unless anime_states.empty? # ステートの更新がなされた場合 if @state_update_flag # ステートIndexを初期化 @loop_state_index = 0 # ループアニメーションの設定 set_loop_animation(anime_states) end @loop_state_animation_count -= 1 # ループカウントが0になった if @loop_state_animation_count == 0 # ステートIndexの更新 @loop_state_index += 1 if @loop_state_index == anime_states.size @loop_state_index = 0 end # ループアニメーションの設定 set_loop_animation(anime_states) end else # 全ステート解除時にループアニメーションを消す if @state_update_flag # アニメーションの更新を検知 @sync_update_flag = true @loop_state_animation_count = 0 @loop_state_index = 0 loop_animation(nil) end end end #-------------------------------------------------------------------------- # ● ループアニメーション設定 #-------------------------------------------------------------------------- def set_loop_animation(anime_states) # アニメーションの更新を検知 @sync_update_flag = true # 表示させるステートアニメーションIDを読み込み animation_id = anime_states[@loop_state_index] # アニメーション読み込み anime_data = $data_animations[animation_id] # フレーム数を設定 @loop_state_animation_count = anime_data.frames.size * State_Extension::LOOP_COUNT # ループアニメーションを設定 loop_animation(anime_data) end #-------------------------------------------------------------------------- # ● ステート表示更新 #-------------------------------------------------------------------------- def update_state # 表示有効判定 case @battler when Game_Actor # アクター有効? return unless State_Extension::ACTOR_STATE when Game_Enemy # エネミー有効? return unless State_Extension::ENEMY_STATE else p "Err: 'Sprite_Battler' can use actor or enemy only" exit end # ステート表示の再セットアップ case State_Extension::STATE_PATTERN when 0 # 通常表示 make_normal_state when 1 # ローテーション make_rotation_state when 2 # ステートアニメーションと同期 make_synchronous_state else p "Err:STATE_PATTERN" exit end # 表示位置の更新。 @state_sprite.x = @battler.screen_x - BITMAP_WIDTH / 2 @state_sprite.y = @battler.screen_y - BITMAP_HEIGHT + State_Extension::STATE_Y @state_sprite.z = @battler.screen_z end #-------------------------------------------------------------------------- # ● 通常のステート表示 #-------------------------------------------------------------------------- def make_normal_state # ステートの更新ありなら更新 draw_state(@battler_state) if @state_update_flag end #-------------------------------------------------------------------------- # ● ローテーションしたステート表示 #-------------------------------------------------------------------------- def make_rotation_state # ステートが付与されている? unless @battler_state.empty? # ローテーションさせるべきか? if State_Extension.do_rotation?(@state_sprite.bitmap, @battler_state, BITMAP_WIDTH) # ローテーションカウント+1 @rotation_count += 1 end # ステートの更新あり? if @state_update_flag @rotation_count = State_Extension::ROT_COUNT @rotation_index = 0 end # ローテーションの更新あり? if @rotation_count == State_Extension::ROT_COUNT @rotation_count = 0 # ローテーションIndex値の更新 @rotation_index += 1 if @rotation_index >= @battler_state.size @rotation_index = 0 end # ローテーションしたステート群の取得 state = State_Extension.rotation_state(@battler_state, @rotation_index) draw_state(state) end else # ステートの更新あり? if @state_update_flag # 表示をクリア @state_sprite.bitmap.clear @rotation_count = 0 @rotation_index = 0 end end end #-------------------------------------------------------------------------- # ● アニメーションと同期したステート表示の更新 #-------------------------------------------------------------------------- def make_synchronous_state # ステートアニメーションの更新あり? if @sync_update_flag # 表示中のアニメーションに応じたステートIDを取得 state = [@battler_state[@loop_state_index]] draw_state(state) end end #-------------------------------------------------------------------------- # ● ステート表示(アイコン/テキスト) # state : ステート用アイコンファイル群 #-------------------------------------------------------------------------- def draw_state(state) # 表示をクリア @state_sprite.bitmap.clear # ステート表示 case State_Extension::STATE_ICON when false # テキスト表示 text = State_Extension.make_state_text(@state_sprite.bitmap, state, BITMAP_WIDTH) # ステート描写 @state_sprite.bitmap.draw_text(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT, text, 1) when true # アイコン表示 # ステート用アイコンのファイル名を取得 icon_state = State_Extension.make_state_icon(state, BITMAP_WIDTH) # ステートのアイコン描写 draw_state_icon(icon_state) else p "Err:STATE_ICON" end end #-------------------------------------------------------------------------- # ● ステート用アイコン表示 # state : ステート用アイコンファイル群 #-------------------------------------------------------------------------- def draw_state_icon(state) # 描画開始位置の決定 x = State_Extension.make_icon_pos_x(state, BITMAP_WIDTH) for i in 0...state.size bitmap = RPG::Cache.icon(state[i]) cw = bitmap.width ch = bitmap.height src_rect = Rect.new(0, 0, cw, ch) @state_sprite.bitmap.blt(x, 0, bitmap, src_rect) # 描画位置を進める x += cw + State_Extension::ICON_INTERVAL end end end