设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
返回列表
+ 发新帖
查看: 145|回复: 0

[转载发布] 简单的"检视战场"脚本New

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    3 小时前
  • 签到天数: 220 天

    连续签到: 8 天

    [LV.7]常住居民III

    9099

    主题

    882

    回帖

    7万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    64785
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    74796

    灌水之王

    发表于 6 天前 | 显示全部楼层 |阅读模式

    最近用DS给自己的游戏加了一堆奇妙插件,难得有这么个简单易用的,分享一下。
    操作方法:在ActorCommand阶段(显示[攻击][防御][技能][物品]的阶段),按下A键,弹出此场景。
    按←→切换左右部分。
    左半边记录了所有Message,一页显示不下,可以按↑↓滚动。
    右半边列出了所有角色和敌人,可以按↑↓切换,底下会有敌人的简介(备注),及角色/敌人附有的状态名(备注,无备注则不显示状态,按优先等级排列)。
    再按A或Esc退出场景。
    自测可用,希望万机之神保佑你……
    [Ruby] 纯文本查看 复制代码
    #==============================================================================
    # ■ 检视战场(独立场景版)
    #------------------------------------------------------------------------------
    # 【操作】
    #   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




                本帖来自P1论坛作者JasperCrazy,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg. blue/forum.php?mod=viewthread&tid=499333  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    帖子地址: 

    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-10-14 04:21 , Processed in 0.133818 second(s), 56 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表