| 赞 | 0 |
| VIP | |
| 好人卡 | |
| 积分 | 2 |
| 经验 | |
| 最后登录 | 2026-10-8 |
| 在线时间 | 68 小时 |
- 梦石
- 0
- 星屑
- 201
- 在线时间
- 68 小时
- 注册时间
- 2019-1-14
- 回帖
- 11
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 JasperCrazy 于 2026-10-8 22:50 编辑
最近用DS给自己的游戏加了一堆奇妙插件,难得有这么个简单易用的,分享一下。
操作方法:在ActorCommand阶段(显示[攻击][防御][技能][物品]的阶段),按下A键,弹出此场景。
按←→切换左右部分。
左半边记录了所有Message,一页显示不下,可以按↑↓滚动。
右半边列出了所有角色和敌人,可以按↑↓切换,底下会有敌人的简介(备注<说明:XX>),及角色/敌人附有的状态名(备注<状态名:XX>,无备注则不显示状态,按优先等级排列)。
再按A或Esc退出场景。
自测可用,希望万机之神保佑你……
- #==============================================================================
- # ■ 检视战场(独立场景版)
- #------------------------------------------------------------------------------
- # 【操作】
- # ActorCommand 阶段按 A / Shift 打开;A / Shift / Esc / X 关闭。
- # 左半为战斗日志:↑↓ 滚动(可按住快速滚动),→ 切到右侧
- # 右半为人物查看:↑↓ 切换成员(首尾循环),← 切回左侧
- # 打开时默认滚到最新一条。
- #
- # 【滚动提示】
- # 左侧有未显示内容时,底部显示黑框 + "按 ↑ 上翻" / "按 ↓ 下翻"
- #
- # 【记录来源】
- # Window_BattleLog#add_text / replace_text、$game_message.add
- #
- # 【转义符处理(记录时固定)】
- # \V[n] → 变量当前值;\name[XX] → "XX:";其他转义符去掉
- #
- # 【数据库备注】
- # 敌人:<说明:XX>(\n 变换行,自动换行)
- # 状态:<状态名:XX>(无此标签则不显示)
- #
- # 【加载位置】
- # Materials 下方、Main 上方,放在所有战斗脚本之后。
- #==============================================================================
- $battle_log_history = nil
- $char_width_cache = {}
- #--------------------------------------------------------------------------
- # ● 滚动参数
- #--------------------------------------------------------------------------
- HOLD_START_FRAMES = 15 # 按住多少帧后开始连续滚动
- HOLD_INTERVAL = 3 # 连续滚动间隔(帧)
- #--------------------------------------------------------------------------
- # ● 转义符处理
- #--------------------------------------------------------------------------
- module BattleLogSanitizer
- def self.sanitize(text)
- return text if text.nil?
- s = text.dup
- s.gsub!(/\\[Vv]\[(\d+)\]/) { $game_variables[$1.to_i].to_s }
- s.gsub!(/\\[Nn]ame\[([^\]]*)\]/) { "#{$1}:" }
- s.gsub!(/\\[A-Za-z_]+\[[^\]]*\]/, "")
- s.gsub!(/\\[A-Za-z_]+/, "")
- s.gsub!(/\\[.><|!^$]/, "")
- s
- end
- end
- #--------------------------------------------------------------------------
- # ● Window_BattleLog — 记录
- #--------------------------------------------------------------------------
- class Window_BattleLog < Window_Selectable
- alias history_log_add_text add_text
- def add_text(text)
- if $battle_log_history
- s = BattleLogSanitizer.sanitize(text)
- $battle_log_history << s unless s.nil? || s.empty?
- end
- history_log_add_text(text)
- end
- alias history_log_replace_text replace_text
- def replace_text(text)
- if $battle_log_history
- s = BattleLogSanitizer.sanitize(text)
- $battle_log_history << s unless s.nil? || s.empty?
- end
- history_log_replace_text(text)
- end
- end
- #--------------------------------------------------------------------------
- # ● Game_Message — 记录事件文字
- #--------------------------------------------------------------------------
- class Game_Message
- alias history_log_message_add add
- def add(text)
- if $battle_log_history && SceneManager.scene.is_a?(Scene_Battle)
- s = BattleLogSanitizer.sanitize(text)
- $battle_log_history << s unless s.nil? || s.empty?
- end
- history_log_message_add(text)
- end
- end
- #--------------------------------------------------------------------------
- # ● Window_BattleHistoryLog — 全屏双面板窗口
- #--------------------------------------------------------------------------
- class Window_BattleHistoryLog < Window_Base
- FONT_SIZE = 20
- STATE_FONT_SIZE = 18
- HINT_FONT_SIZE = 18
- LINE_HEIGHT = 24
- MAX_MEMBERS = 9
- STATE_ICON_W = 24
- def initialize
- super(0, 0, Graphics.width, Graphics.height)
- contents.font.size = FONT_SIZE
- @active = false
- @close_requested = false
- @side = :left
- @left_oy = 0
- @member_index = 0
- @data = []
- @battler_list = []
- @history_lines = []
- @prev_press = {}
- @hold = {}
- self.z = 1000
- self.openness = 0
- end
- def close_requested?; @close_requested; end
- #--------------------------------------------------------------------------
- # ● 激活:快照当前所有按键状态
- #--------------------------------------------------------------------------
- def activate
- @active = true
- @prev_press = {}
- @hold = {}
- [:UP, :DOWN, :LEFT, :RIGHT, :A, :B, :X].each do |k|
- @prev_press[k] = Input.press?(k)
- @hold[k] = nil
- end
- end
- def deactivate; @active = false; end
- def active?; @active; end
- def left_width; (contents.width * 0.5).to_i - 8; end
- def right_x; left_width + 16; end
- def right_width; contents.width - right_x - 4; end
- def right_top_height
- [MAX_MEMBERS * LINE_HEIGHT + 4, contents.height - 80].min
- end
- def right_bottom_y; right_top_height + 6; end
- #--------------------------------------------------------------------------
- # ● 字符宽度缓存
- #--------------------------------------------------------------------------
- def char_width(ch)
- key = [contents.font.size, ch]
- $char_width_cache[key] ||= contents.text_size(ch).width
- end
- #--------------------------------------------------------------------------
- # ● 设置数据
- #--------------------------------------------------------------------------
- def set_data(history, battlers)
- @data = (history || []).dup
- @battler_list = (battlers || []).first(MAX_MEMBERS)
- @member_index = 0
- @side = :left
- @close_requested = false
- rebuild
- @left_oy = left_max_oy
- refresh
- end
- def rebuild
- contents.font.size = FONT_SIZE
- @history_lines = []
- @data.each { |text| @history_lines.concat(wrap_text(text, left_width)) }
- end
- #--------------------------------------------------------------------------
- # ● 自动换行(逐字增量测量)
- #--------------------------------------------------------------------------
- def wrap_text(text, max_width)
- return [""] if text.empty?
- return [""] if text.nil?
- lines = []
- current = ""
- current_w = 0
- text.each_char do |c|
- if c == "\n"
- lines << current
- current = ""
- current_w = 0
- next
- end
- w = char_width(c)
- if current_w + w > max_width
- lines << current
- current = c
- current_w = w
- else
- current << c
- current_w += w
- end
- end
- lines << current unless current.empty?
- lines
- end
- def left_max_oy
- [@history_lines.size * LINE_HEIGHT - contents.height, 0].max
- end
- #--------------------------------------------------------------------------
- # ● 绘制
- #--------------------------------------------------------------------------
- def refresh
- contents.clear
- draw_left_panel
- draw_left_hints
- draw_separator
- draw_right_panel
- draw_focus_frame
- end
- def draw_left_panel
- w = left_width
- y = -@left_oy
- @history_lines.each do |line|
- if y + LINE_HEIGHT > 0 && y < contents.height
- contents.draw_text(0, y, w, LINE_HEIGHT, line)
- end
- y += LINE_HEIGHT
- break if y > contents.height
- end
- end
- #--------------------------------------------------------------------------
- # ● 左侧滚动提示:↑ 在顶部,↓ 在底部
- #--------------------------------------------------------------------------
- def draw_left_hints
- has_prev = @left_oy > 0
- has_next = @left_oy < left_max_oy
- lh = LINE_HEIGHT
- old_color = contents.font.color.clone
- old_size = contents.font.size
- contents.font.color = Color.new(255, 220, 100)
- contents.font.size = HINT_FONT_SIZE
- # 顶部:"↑ 上翻"
- if has_prev
- top_rect = Rect.new(0, 0, left_width, lh)
- contents.fill_rect(top_rect, Color.new(0, 0, 0, 200))
- contents.draw_text(top_rect, "↑ 上翻", 1)
- end
- # 底部:"↓ 下翻"
- if has_next
- bottom_rect = Rect.new(0, contents.height - lh, left_width, lh)
- contents.fill_rect(bottom_rect, Color.new(0, 0, 0, 200))
- contents.draw_text(bottom_rect, "↓ 下翻", 1)
- end
- contents.font.color = old_color
- contents.font.size = old_size
- end
- def draw_separator
- x = left_width + 4
- contents.fill_rect(x, 0, 2, contents.height, Color.new(255, 255, 255, 60))
- end
- def draw_right_panel
- x = right_x
- w = right_width
- @battler_list.each_with_index do |b, i|
- y = i * LINE_HEIGHT
- if i == @member_index && @side == :right
- contents.fill_rect(x - 4, y - 1, w, LINE_HEIGHT + 2,
- Color.new(255, 200, 50, 80))
- draw_border(x - 4, y - 1, w, LINE_HEIGHT + 2)
- end
- contents.draw_text(x, y, w, LINE_HEIGHT, b.name)
- end
- contents.fill_rect(x, right_top_height, w, 2, Color.new(255, 255, 255, 80))
- draw_member_detail(x, right_bottom_y, w, contents.height - right_bottom_y)
- end
- def draw_member_detail(x, y, w, h)
- return if @battler_list.empty?
- b = @battler_list[@member_index]
- return unless b
- contents.draw_text(x, y, w, LINE_HEIGHT, b.name)
- y += LINE_HEIGHT
- desc = get_description(b)
- if desc && !desc.empty?
- wrap_text(desc, w).each do |line|
- break if y + LINE_HEIGHT > contents.height
- contents.draw_text(x, y, w, LINE_HEIGHT, line)
- y += LINE_HEIGHT
- end
- end
- y += 6
- draw_states_two_columns(b, x, y, w, contents.height - y)
- end
- #--------------------------------------------------------------------------
- # ● 两列显示状态
- #--------------------------------------------------------------------------
- def draw_states_two_columns(battler, x, y, w, h)
- return if h <= 0
- old_size = contents.font.size
- contents.font.size = STATE_FONT_SIZE
- begin
- states = battler.states
- .sort_by { |s| [-s.priority, s.id] }
- .select { |s| state_display_name(s) }
- return if states.empty?
- col_w = w / 2
- text_max = col_w - STATE_ICON_W - 8
- first_col = []
- cur_y = 0
- remaining = []
- states.each do |s|
- if cur_y + LINE_HEIGHT > h
- remaining << s
- next
- end
- name = state_display_name(s)
- too_long = contents.text_size(name).width > text_max
- first_col << [s, too_long, cur_y]
- cur_y += LINE_HEIGHT
- end
- first_col.each do |s, too_long, offset_y|
- name = state_display_name(s)
- row_y = y + offset_y
- draw_icon(s.icon_index, x, row_y)
- if too_long
- contents.draw_text(x + STATE_ICON_W, row_y,
- w - STATE_ICON_W, LINE_HEIGHT, name)
- else
- contents.draw_text(x + STATE_ICON_W, row_y,
- col_w - STATE_ICON_W, LINE_HEIGHT, name)
- end
- end
- second_x = x + col_w
- cur_y = 0
- remaining.each do |s|
- while cur_y + LINE_HEIGHT <= h
- row_index = cur_y / LINE_HEIGHT
- if row_index < first_col.size && first_col[row_index][1]
- cur_y += LINE_HEIGHT
- else
- break
- end
- end
- break if cur_y + LINE_HEIGHT > h
- name = state_display_name(s)
- row_y = y + cur_y
- draw_icon(s.icon_index, second_x, row_y)
- contents.draw_text(second_x + STATE_ICON_W, row_y,
- col_w - STATE_ICON_W, LINE_HEIGHT, name)
- cur_y += LINE_HEIGHT
- end
- ensure
- contents.font.size = old_size
- end
- end
- def get_description(battler)
- return nil unless battler.is_a?(Game_Enemy)
- note = battler.enemy.note
- return nil if note.nil? || note.empty?
- if note =~ /<说明[::]\s*([^>]+)>/m
- return $1.gsub("\\n", "\n").strip
- end
- nil
- end
- def state_display_name(state)
- return nil if state.note.nil?
- if state.note =~ /<状态名[::]\s*([^>]+)>/
- return $1.strip
- end
- nil
- end
- def draw_focus_frame
- draw_border(0, 0, left_width, contents.height) if @side == :left
- end
- def draw_border(x, y, w, h)
- c = Color.new(255, 200, 50)
- contents.fill_rect(x, y, w, 2, c)
- contents.fill_rect(x, y+h-2, w, 2, c)
- contents.fill_rect(x, y, 2, h, c)
- contents.fill_rect(x+w-2, y, 2, h, c)
- end
- #--------------------------------------------------------------------------
- # ● 输入状态更新(每帧一次)
- #--------------------------------------------------------------------------
- def update_input_state
- [:UP, :DOWN, :LEFT, :RIGHT, :A, :B, :X].each do |k|
- now = Input.press?(k)
- was = @prev_press[k] || false
- just = now && !was
- @prev_press[k] = now
- if just
- @hold[k] = 0
- elsif now
- @hold[k] = (@hold[k] || 0) + 1
- else
- @hold[k] = nil
- end
- end
- end
- # 首次按下(严格上升沿)
- def just_pressed?(key)
- @hold[key] == 0
- end
- # 首次按下 OR 按住后连续触发
- def triggered?(key)
- c = @hold[key]
- return false if c.nil?
- return true if c == 0
- c >= HOLD_START_FRAMES && (c - HOLD_START_FRAMES) % HOLD_INTERVAL == 0
- end
- #--------------------------------------------------------------------------
- # ● 更新
- #--------------------------------------------------------------------------
- def update
- super
- update_input_state
- return unless @active && openness > 0
- # 关闭
- if just_pressed?(:A) || just_pressed?(:B) || just_pressed?(:X)
- @close_requested = true
- deactivate
- close
- return
- end
- if @side == :left
- if just_pressed?(:RIGHT)
- @side = :right
- refresh
- elsif triggered?(:UP)
- @left_oy = [@left_oy - LINE_HEIGHT, 0].max
- refresh
- elsif triggered?(:DOWN)
- @left_oy = [@left_oy + LINE_HEIGHT, left_max_oy].min
- refresh
- end
- else
- if just_pressed?(:LEFT)
- @side = :left
- refresh
- elsif triggered?(:UP)
- move_cursor(-1)
- elsif triggered?(:DOWN)
- move_cursor(1)
- end
- end
- end
- def move_cursor(delta)
- return if @battler_list.empty?
- @member_index = (@member_index + delta) % @battler_list.size
- refresh
- end
- end
- #--------------------------------------------------------------------------
- # ● Scene_BattleHistory — 独立场景
- #--------------------------------------------------------------------------
- class Scene_BattleHistory < Scene_Base
- def start
- super
- create_background
- create_window
- end
- def create_background
- @bg_sprite = Sprite.new
- @bg_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
- @bg_sprite.bitmap.fill_rect(0, 0, Graphics.width, Graphics.height,
- Color.new(0, 0, 0, 200))
- @bg_sprite.z = 500
- end
- def create_window
- battlers = $game_party.members + $game_troop.members
- @window = Window_BattleHistoryLog.new
- @window.set_data($battle_log_history, battlers)
- @window.openness = 255
- @window.activate
- end
- def perform_transition
- Graphics.transition(4)
- end
- def update
- super
- @window.update
- if @window.close_requested? && @window.openness == 0
- return_scene
- end
- end
- def terminate
- @window.dispose
- @bg_sprite.dispose
- super
- end
- end
- #--------------------------------------------------------------------------
- # ● Scene_Battle — 集成
- #--------------------------------------------------------------------------
- class Scene_Battle < Scene_Base
- alias history_log_battle_start battle_start
- def battle_start
- $battle_log_history = []
- history_log_battle_start
- end
- alias history_log_turn_end turn_end
- def turn_end
- history_log_turn_end
- if $battle_log_history && !$battle_log_history.empty? && $battle_log_history.last != ""
- $battle_log_history << ""
- end
- end
- alias history_log_update update
- def update
- history_log_update
- update_battle_history_log
- end
- def update_battle_history_log
- @history_cooldown ||= 0
- @history_cooldown -= 1 if @history_cooldown > 0
- return if @history_cooldown > 0
- return unless @actor_command_window
- return unless @actor_command_window.active
- return unless Input.trigger?(:A) || Input.trigger?(:X)
- open_battle_history_log
- end
- def open_battle_history_log
- saved_index = @actor_command_window ? @actor_command_window.index : 0
- saved_oy = @actor_command_window ? @actor_command_window.oy : 0
- @actor_command_window.deactivate if @actor_command_window
- SceneManager.call(Scene_BattleHistory)
- SceneManager.scene.main
- if SceneManager.respond_to?(:force_recall)
- SceneManager.force_recall(self)
- else
- SceneManager.instance_variable_set(:@scene, self)
- end
- if @actor_command_window && !@actor_command_window.disposed?
- @actor_command_window.refresh
- @actor_command_window.activate
- @actor_command_window.select(saved_index)
- @actor_command_window.oy = saved_oy
- end
- refresh_status
- # 关键:解冻画面(子场景退出时执行了 Graphics.freeze)
- perform_transition
- @history_cooldown = 3
- end
- end
复制代码
|
|