Project1

标题: 让没有头像的事件也使用FUKI对话框的问题 [打印本页]

作者: zjlwdwd    时间: 2010-6-23 13:55
标题: 让没有头像的事件也使用FUKI对话框的问题
本帖最后由 提妲 于 2010-7-5 12:51 编辑
  1. #==============================================================================
  2. # vx呼出对话框 by 沉影不器
  3. #------------------------------------------------------------------------------
  4. # 呼出对话框原作者: パラ犬(日)
  5. #------------------------------------------------------------------------------
  6. # 『素材准备』
  7. #   ① 按vx默认头像素材的格式,但要求每个头像文件所有8格均为同一人的表
  8. #      情并且所有表情朝向一致(默认是正面偏右), 以角色(对话者)名称来命
  9. #      名每个头像文件,用于对话框中自动生成对话者名称.
  10. #   ② vx窗体较xp更精致,头像不宜太大.
  11. #      小头像不宜超过96*96; 半身像不宜超过140*140
  12. #   ③ 呼出对话框箭头图标的命名规则为:
  13. #      制作上下两个对话框箭头图标, 分别命名为:
  14. #      您设定的对话框皮肤名称后加"_arrow_down"(对应下箭头)
  15. #      或"_arrow_up"(对应上箭头), 并存放在system文件夹内.
  16. #
  17. # 『脚本使用』
  18. #   ① 复制脚本插入到Main之前.
  19. #   ② 请务必看完脚本的设定部分,并根据游戏素材的情况设定好各参数
  20. #      脚本第 47-98 行为默认设定部分
  21. #      脚本第 107-113 行为游戏中可更改的设定部分.
  22. #   ③ 地图上跟角色进行对话的事件名称使用与头像素材一致的名称, 即对话
  23. #      者的名称,以便脚本根据名称找到对应事件.
  24. #   ④ 可在游戏中更改参数的说明:
  25. #      ▼ 以第行的fuki_font_name举例
  26. #         对话之前,在事件脚本中输入$game_temp.fuki_font_name = "宋体"
  27. #         将把对话框使用的字体改为"宋体".
  28. #      ▼ 以第行的face_type举例
  29. #         对话之前,在事件脚本中输入$game_temp.face_type = 1
  30. #         将把头像的水平显示位置改为"头像在右".
  31. #      其它可改参数同上.
  32. #
  33. # 『脚本自动完成部分的补充说明』
  34. #   ① 根据头像的文件名自动填写对话者名称,这将占用一行对话框的位置
  35. #   ② 脚本根据事件名称,在屏幕范围内自动查找对话者,如果对话者在范围内
  36. #      不存在,则使用普通对话框,自动调节对话框大小,自动水平居中显示,垂
  37. #      直方向仍由对话事件本身决定.
  38. #   ③ 默认头像素材为正面偏右,当您指定头像显示在右时,脚本将对头像素材
  39. #      镜像处理,您的头像素材中须注意这点
  40. #------------------------------------------------------------------------------
  41. # 最后一句提示: 善用素材,配合默认设定的修改. 感谢您看完烦琐的说明.
  42. #==============================================================================

  43. #==============================================================================
  44. # ■ 默认设定(部分设定允许在游戏中随时更改,见脚本第 107-113 行)
  45. #==============================================================================
  46. module FUKI
  47.   #--------------------------------------------------------------------------
  48.   # ◎ 坐标微调
  49.   #--------------------------------------------------------------------------
  50.   # 对话框
  51.     MSG_Y_ADJ = 8               # 使用呼出对话框时,角色和对话框的纵向间距
  52.   # 头像
  53.     FACE_X_ADJ = 8              # 头像向对话框内横向缩进(避免遮盖对话框外框)
  54.     FACE_Y_ADJ = -2             # 头像向对话框内纵向缩进(避免遮盖对话框外框)
  55.   # 名称背景条
  56.     NAME_BAR_X = 6              # 名称背景条相对于对话框的起始横坐标
  57.   # 呼出对话框箭头
  58.     ARR0W_UP_X_ADJ = 0          # 上箭头的横向调节
  59.     ARR0W_UP_Y_ADJ = 6          # 上箭头的纵向调节
  60.     ARR0W_DOWN_X_ADJ = 0        # 下箭头的横向调节
  61.     ARR0W_DOWN_Y_ADJ = -6       # 下箭头的纵向调节
  62.   #--------------------------------------------------------------------------
  63.   # ◎ 窗体设定
  64.   #--------------------------------------------------------------------------
  65.     SKIN = "window"             # 设定对话框Skin
  66.     OPACITY = 255               # 窗口透明度
  67.   #--------------------------------------------------------------------------
  68.   # ◎ 文字设定
  69.   #    文字颜色说明: 使用Window_Base中text_color(n)的颜色代码
  70.   #--------------------------------------------------------------------------
  71.   # 字体
  72.     FONT_NAME = "黑体"          # 对话框字体
  73.     FONT_SIZE = 14              # 对话框文字字号
  74.     FONT_SHADOW = true          # 对话框文字阴影
  75.   # 文字颜色
  76.     MSG_COLOR = 0               # 对话框文字颜色
  77.     NAME_COLOR = 16             # 角色名称文字颜色
  78.   #--------------------------------------------------------------------------
  79.   # ◎ 头像设定
  80.   #--------------------------------------------------------------------------
  81.   # 头像始终在对话框内(默认使用半身像, 则为 false)
  82.     IN_CONTENT = true
  83.   # 头像垂直对齐方式(0: 顶端对齐; 1: 居中对齐; 2: 底端对齐)
  84.     V_ALIGN = 2
  85.   # 头像水平显示位置(0: 头像在左; 1: 头像在右)
  86.     H_ALIGN = 1
  87.   #--------------------------------------------------------------------------
  88.   # ◎ 自动显示名称设定
  89.   #--------------------------------------------------------------------------
  90.     NAME_Y_ADJ = 6              # 显示名称时,对话者名称与对话内容之间的距离
  91.     NAME_BAR_COLOR = 0         # 名称背景条颜色
  92.     NAME_BAR_OPACITY = 72       # 名称背景条透明度
  93.   #--------------------------------------------------------------------------
  94.   # ◎ 附带功能设定
  95.   #--------------------------------------------------------------------------
  96.   # 超过指定时间,玩家无输入则自动关闭对话框(单位: 帧)
  97.     AUTO_CLOSE_TIME = 60*60     # 默认为1分钟
  98.   # 默认打字速度修正
  99.     SPEED = 2
  100. end

  101. #==============================================================================
  102. # ■ Game_Temp
  103. #==============================================================================
  104. class Game_Temp
  105.   #--------------------------------------------------------------------------
  106.   # ● 定义实例变量
  107.   #--------------------------------------------------------------------------
  108.   attr_accessor :fuki_font_name   # 呼出对话框字体
  109.   attr_accessor :fuki_font_size   # 呼出对话框字号
  110.   attr_accessor :fuki_msg_color   # 呼出对话框文字颜色
  111.   attr_accessor :fuki_name_color  # 角色名称文字颜色
  112.   attr_accessor :face_type        # 头像水平显示位置
  113.   attr_accessor :auto_close       # 对话框自动关闭时间
  114.   attr_accessor :speed            # 对话框打字速度修正
  115.   attr_accessor :fuki_noface_name
  116.   #--------------------------------------------------------------------------
  117.   # ● 初始化对象
  118.   #--------------------------------------------------------------------------
  119.   alias ini initialize
  120.   def initialize
  121.     ini
  122.     @fuki_font_name = FUKI::FONT_NAME
  123.     @fuki_font_size = FUKI::FONT_SIZE
  124.     @fuki_msg_color = FUKI::MSG_COLOR
  125.     @fuki_name_color = FUKI::NAME_COLOR
  126.     @face_type = FUKI::H_ALIGN
  127.     @auto_close = FUKI::AUTO_CLOSE_TIME
  128.     @speed = FUKI::SPEED
  129.     @fuki_noface_name=""
  130.   end
  131. end

  132. #==============================================================================
  133. # ■ Game_Event
  134. #==============================================================================
  135. class Game_Event
  136.   #--------------------------------------------------------------------------
  137.   # ◎ 返回事件名称
  138.   #--------------------------------------------------------------------------
  139.   def name
  140.     return @event.name
  141.   end
  142. end

  143. #==============================================================================
  144. # ■ Window_NumberInput
  145. #==============================================================================
  146. class Window_NumberInput < Window_Base
  147.   #--------------------------------------------------------------------------
  148.   # ◎ 刷新
  149.   #--------------------------------------------------------------------------
  150.   def refresh
  151.     self.contents.clear
  152.     self.contents.font.name = $game_temp.fuki_font_name
  153.     self.contents.font.size = $game_temp.fuki_font_size
  154.     self.contents.font.shadow = FUKI::FONT_SHADOW
  155.     self.contents.font.color = normal_color
  156.     s = sprintf("%0*d", @digits_max, @number)
  157.     for i in 0...@digits_max
  158.       self.contents.draw_text\
  159.       (24 + i * 16, 0, 16, FUKI::FONT_SIZE + 2, s[i,1], 1)
  160.     end
  161.   end
  162.   #--------------------------------------------------------------------------
  163.   # ◎ 更新光标
  164.   #--------------------------------------------------------------------------
  165.   def update_cursor
  166.     self.cursor_rect.set(24 + @index * 16, 0, 16, FUKI::FONT_SIZE + 2)
  167.   end
  168. end

  169. #==============================================================================
  170. # ■ Window_Message
  171. #==============================================================================
  172. class Window_Message < Window_Selectable
  173.   #--------------------------------------------------------------------------
  174.   # ◎ 定义实例变量
  175.   #--------------------------------------------------------------------------
  176.   attr_accessor :user_cancel              # 暂时使用默认对话框
  177.   attr_accessor :face_type                # 头像水平显示位置
  178.   #--------------------------------------------------------------------------
  179.   # ◎ 常量
  180.   #--------------------------------------------------------------------------
  181.   MAX_LINE = 5                            # 最大行数
  182.   #--------------------------------------------------------------------------
  183.   # ◎ 初始化对象
  184.   #--------------------------------------------------------------------------
  185.   def initialize
  186.     super(0, 288, 544, 128)
  187.     self.z = 200
  188.     self.active = false
  189.     self.index = -1
  190.     self.openness = 0
  191.     @opening = false                      # 窗口正在打开的标志
  192.     @closing = false                      # 窗口正在关闭的标志
  193.     @text = nil                           # 已经没有可显示的文章
  194.     @contents_x = 0                       # 下一条文字描绘的 X 坐标
  195.     @contents_y = 0                       # 下一条文字描绘的 Y 坐标
  196.     @line_count = 0                       # 现在描绘的行数
  197.     @wait_count = 0                       # 等待计数
  198.     @background = 0                       # 背景类型
  199.     @position = 2                         # 显示位置
  200.     @show_fast = false                    # 快速显示标志
  201.     @line_show_fast = false               # 以行为单位快速显示
  202.     @pause_skip = false                   # 省略等待输入标志
  203.     @update_pos = false                   # 对话框跟随开关关闭
  204.     @show_name  = false                   # 名称显示开关关闭
  205.     @fuki_pause = false                   # 为了方便代替window类的pause
  206.     @user_cancel = false                  # 暂时使用默认对话框的标志
  207.     # 生成对象
  208.     create_gold_window
  209.     create_number_input_window
  210.     create_back_sprite
  211.     create_face_sprite                    # 生成头像
  212.     create_namebar_sprite                 # 生成名称背景条
  213.     create_arrow_sprite                   # 生成对话框箭头
  214.     # 透明度设定
  215.     set_opacity(self)
  216.     set_opacity(@arrow_sprite)
  217.   end
  218.   #--------------------------------------------------------------------------
  219.   # ◎ 释放
  220.   #--------------------------------------------------------------------------
  221.   def dispose
  222.     super
  223.     dispose_gold_window
  224.     dispose_number_input_window
  225.     dispose_back_sprite
  226.     dispose_face_sprite                   # 释放头像
  227.     dispose_arrow_sprite                  # 释放对话框箭头
  228.   end
  229.   #--------------------------------------------------------------------------
  230.   # ◎ 更新画面
  231.   #--------------------------------------------------------------------------
  232.   def update
  233.     super
  234.     update_gold_window
  235.     update_number_input_window
  236.     update_back_sprite
  237.     update_show_fast
  238.     if @update_pos
  239.       reset_msg_pos                         # 重设对话框坐标
  240.       reset_namebar_bitmap                  # 重绘名称背景条
  241.     end
  242.     # 除窗口关闭以外
  243.     unless @opening or @closing
  244.       # 文章内等待中
  245.       if @wait_count > 0
  246.         @wait_count -= 1
  247.       # 等待文章翻页待机中
  248.       elsif @fuki_pause
  249.         input_pause
  250.       # 正在输入选择项
  251.       elsif self.active
  252.         input_choice
  253.       # 正在输入数值
  254.       elsif @number_input_window.visible
  255.         input_number
  256.       # 还有剩余的文章
  257.       elsif @text != nil
  258.         update_message                      # 更新消息
  259.       # 继续的情况
  260.       elsif continue?
  261.         start_message                       # 开始消息
  262.         reset_msg_size                      # 重设对话框尺寸
  263.         reset_contents                      # 重设位图容器
  264.         reset_msg_pos                       # 重设对话框坐标
  265.         reset_namebar_bitmap                # 重绘名称背景条
  266.         $game_message.visible = true
  267.         open                                # 打开窗口
  268.         @face_sprite.visible = true
  269.       # 不继续的情况
  270.       else
  271.         @face_sprite.visible = @closing     # 关闭头像显示
  272.         @arrow_sprite.visible = @closing    # 关闭头像显示
  273.         close                               # 关闭窗口
  274.         $game_message.visible = @closing
  275.       end
  276.     end
  277.     # 显示对话时,计算自动关闭时间
  278.     if $game_message.visible
  279.       if $game_temp.auto_close > 0
  280.         $game_temp.auto_close -= 1
  281.       else
  282.         terminate_message
  283.       end
  284.     end
  285.   end
  286.   #--------------------------------------------------------------------------
  287.   # ◎ 还原默认设定
  288.   #--------------------------------------------------------------------------
  289.   def default_setting
  290.     @user_cancel = false                           # 暂时使用默认对话框的标志
  291.     $game_temp.face_type = FUKI::H_ALIGN           # 头像水平显示位置
  292.     $game_temp.speed = FUKI::SPEED                 # 对话打字速度修正
  293.     $game_temp.auto_close = FUKI::AUTO_CLOSE_TIME  # 自动关闭时间
  294.     @namebar_sprite.bitmap.clear
  295.   end
  296.   #--------------------------------------------------------------------------
  297.   # ◎ 头像图像预留宽度
  298.   #--------------------------------------------------------------------------
  299.   def face_width
  300.     name = $game_message.face_name
  301.     #print(name)
  302.     return 0 if name == ""
  303.     return Cache.face(name).width/4# + FUKI::FACE_X_ADJ
  304.   end
  305.   #--------------------------------------------------------------------------
  306.   # ◎ 头像图像预留高度
  307.   #--------------------------------------------------------------------------
  308.   def face_height
  309.     name = $game_message.face_name
  310.     return 0 if name == ""
  311.     return Cache.face(name).height/2# + FUKI::FACE_Y_ADJ
  312.   end
  313.   #--------------------------------------------------------------------------
  314.   # ◎ 是否使用呼出对话框
  315.   #--------------------------------------------------------------------------
  316.   def use_fuki?
  317.     # 考虑细分条件
  318.     return false if @user_cancel                 # 暂时使用默认对话框的标志
  319.     return false if get_character_pos == nil     # 找不到说话者坐标时
  320.     return true
  321.   end
  322.   #--------------------------------------------------------------------------
  323.   # ● 生成所持金窗口
  324.   #--------------------------------------------------------------------------
  325.   def create_gold_window
  326.     @gold_window = Window_Gold.new(384, 0)
  327.     @gold_window.openness = 0
  328.   end
  329.   #--------------------------------------------------------------------------
  330.   # ● 生成数值输入窗口
  331.   #--------------------------------------------------------------------------
  332.   def create_number_input_window
  333.     @number_input_window = Window_NumberInput.new
  334.     @number_input_window.visible = false
  335.   end
  336.   #--------------------------------------------------------------------------
  337.   # ● 生成背景活动块
  338.   #--------------------------------------------------------------------------
  339.   def create_back_sprite
  340.     @back_sprite = Sprite.new
  341.     @back_sprite.bitmap = Cache.system("MessageBack")
  342.     @back_sprite.visible = (@background == 1)
  343.     @back_sprite.z = 190
  344.   end
  345.   #--------------------------------------------------------------------------
  346.   # ◎ 生成头像
  347.   #--------------------------------------------------------------------------
  348.   def create_face_sprite
  349.     @face_sprite = Sprite.new
  350.     @face_sprite.bitmap = Bitmap.new(1,1)
  351.     @face_sprite.z = self.z + 2
  352.     @face_sprite.visible = false
  353.     @old_name = ""                        # 判断头像是否改变
  354.     @old_index = 0                        # 判断头像是否改变
  355.   end
  356.   #--------------------------------------------------------------------------
  357.   # ◎ 生成对话框箭头
  358.   #--------------------------------------------------------------------------
  359.   def create_arrow_sprite
  360.     @arrow_sprite = Sprite.new
  361.     @arrow_sprite.bitmap = Bitmap.new(1, 1)
  362.     @arrow_sprite.z = self.z + 1
  363.     @arrow_sprite.visible = false
  364.    end
  365.   #--------------------------------------------------------------------------
  366.   # ◎ 生成名称背景条
  367.   #--------------------------------------------------------------------------
  368.   def create_namebar_sprite
  369.     @namebar_sprite = Sprite.new
  370.     @namebar_sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
  371.     @namebar_sprite.z = self.z + 1
  372.    end
  373.   #--------------------------------------------------------------------------
  374.   # ◎ 释放名称背景条
  375.   #--------------------------------------------------------------------------
  376.   def dispose_namebar_sprite
  377.     @namebar_sprite.dispose
  378.   end
  379.   #--------------------------------------------------------------------------
  380.   # ◎ 释放对话框箭头
  381.   #--------------------------------------------------------------------------
  382.   def dispose_arrow_sprite
  383.     @arrow_sprite.dispose
  384.   end
  385.   #--------------------------------------------------------------------------
  386.   # ◎ 释放头像
  387.   #--------------------------------------------------------------------------
  388.   def dispose_face_sprite
  389.     @face_sprite.dispose
  390.   end
  391.   #--------------------------------------------------------------------------
  392.   # ● 释放所持金窗口
  393.   #--------------------------------------------------------------------------
  394.   def dispose_gold_window
  395.     @gold_window.dispose
  396.   end
  397.   #--------------------------------------------------------------------------
  398.   # ● 释放数值输入窗口
  399.   #--------------------------------------------------------------------------
  400.   def dispose_number_input_window
  401.     @number_input_window.dispose
  402.   end
  403.   #--------------------------------------------------------------------------
  404.   # ● 释放背景活动块
  405.   #--------------------------------------------------------------------------
  406.   def dispose_back_sprite
  407.     @back_sprite.dispose
  408.   end
  409.   #--------------------------------------------------------------------------
  410.   # ● 更新所持金窗口
  411.   #--------------------------------------------------------------------------
  412.   def update_gold_window
  413.     @gold_window.update
  414.   end
  415.   #--------------------------------------------------------------------------
  416.   # ● 更新数值输入窗口
  417.   #--------------------------------------------------------------------------
  418.   def update_number_input_window
  419.     @number_input_window.update
  420.   end
  421.   #--------------------------------------------------------------------------
  422.   # ● 更新背景活动块
  423.   #--------------------------------------------------------------------------
  424.   def update_back_sprite
  425.     @back_sprite.visible = (@background == 1)
  426.     @back_sprite.y = y - 16
  427.     @back_sprite.opacity = openness
  428.     @back_sprite.update
  429.   end
  430.   #--------------------------------------------------------------------------
  431.   # ● 更新快速显示标志
  432.   #--------------------------------------------------------------------------
  433.   def update_show_fast
  434.     if @fuki_pause or self.openness < 255
  435.       @show_fast = false
  436.     elsif Input.trigger?(Input::C) and @wait_count < 2
  437.       @show_fast = true
  438.     elsif not Input.press?(Input::C)
  439.       @show_fast = false
  440.     end
  441.     if @show_fast and @wait_count > 0
  442.       @wait_count -= 1
  443.     end
  444.   end
  445.   #--------------------------------------------------------------------------
  446.   # ● 判断下一消息继续显示
  447.   #--------------------------------------------------------------------------
  448.   def continue?
  449.     return true if $game_message.num_input_variable_id > 0
  450.     return false if $game_message.texts.empty?
  451.     if self.openness > 0 and not $game_temp.in_battle
  452.       return false if @background != $game_message.background
  453.       return false if @position != $game_message.position
  454.     end
  455.     return true
  456.   end
  457.   #--------------------------------------------------------------------------
  458.   # ◎ 开始显示消息
  459.   #--------------------------------------------------------------------------
  460.   def start_message
  461.     @show_name = false   
  462.     if $game_message.face_name.empty? and $game_temp.fuki_noface_name!=""
  463.       
  464.       text = "\\C[#{$game_temp.fuki_name_color}]" +
  465.             $game_temp.fuki_noface_name.to_s + ":" +
  466.              "\\C[#{$game_temp.fuki_msg_color}]"
  467.       $game_message.texts.unshift(text)
  468.       @show_name = true      
  469.     end
  470.     # 重新初始化名称标志
  471.     unless $game_message.face_name.empty?
  472.       # 新增名称并设定文字颜色
  473.       text = "\\C[#{$game_temp.fuki_name_color}]" +
  474.              $game_message.face_name.to_s + ":" +
  475.              "\\C[#{$game_temp.fuki_msg_color}]"
  476.       $game_message.texts.unshift(text)
  477.       @show_name = true                             # 设定名称标志
  478.     end
  479.     @text = ""
  480.     for i in 0...$game_message.texts.size
  481.       @text += "  " if i >= $game_message.choice_start
  482.       @text += $game_message.texts[i].clone + "\x00"
  483.     end
  484.     @item_max = $game_message.choice_max
  485.     convert_special_characters
  486.     new_page
  487.     @update_pos = true                              # 对话框跟随开关关闭
  488.   end
  489.   #--------------------------------------------------------------------------
  490.   # ◎ 更换页面处理
  491.   #--------------------------------------------------------------------------
  492.   def new_page
  493.     contents.clear
  494.     if $game_message.face_name.empty?               # 清除上一次的头像
  495.       @contents_x = 0
  496.       @face_sprite.bitmap.dispose unless @face_sprite.bitmap.disposed?
  497.     else                                            # 初始化头像重绘环境
  498.       name = $game_message.face_name
  499.       index = $game_message.face_index
  500.       if @old_name != name or @old_index != index
  501.         @old_name = name
  502.         @old_index = index
  503.       end
  504.       draw_fuki_face(name, index)                   # 重绘头像
  505.       @contents_x = face_width                      # 根据头像修正横坐标
  506.     end
  507.     @contents_y = 0
  508.     @line_count = 0
  509.     @show_fast = false
  510.     @line_show_fast = false
  511.     @pause_skip = false
  512.     contents.font.color = text_color(0)             # 还原默认文字颜色
  513.   end
  514.   #--------------------------------------------------------------------------
  515.   # ● 换行处理
  516.   #--------------------------------------------------------------------------
  517.   def new_line
  518.     if $game_message.face_name.empty?
  519.       @contents_x = 0
  520.     else
  521.       name = $game_message.face_name
  522.       @contents_x = face_width
  523.     end
  524.     @contents_y += FUKI::FONT_SIZE + 2
  525.     @line_count += 1
  526.     @line_show_fast = false
  527.   end
  528.   #--------------------------------------------------------------------------
  529.   # ● 特殊文字变换
  530.   #--------------------------------------------------------------------------
  531.   def convert_special_characters
  532.     @text.gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
  533.     @text.gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
  534.     @text.gsub!(/\\N\[([0-9]+)\]/i) { $game_actors[$1.to_i].name }
  535.     @text.gsub!(/\\C\[([0-9]+)\]/i) { "\x01[#{$1}]" }
  536.     @text.gsub!(/\\G/)              { "\x02" }
  537.     @text.gsub!(/\\\./)             { "\x03" }
  538.     @text.gsub!(/\\\|/)             { "\x04" }
  539.     @text.gsub!(/\\!/)              { "\x05" }
  540.     @text.gsub!(/\\>/)              { "\x06" }
  541.     @text.gsub!(/\\</)              { "\x07" }
  542.     @text.gsub!(/\\\^/)             { "\x08" }
  543.     @text.gsub!(/\\\\/)             { "\\" }
  544.   end
  545.   #--------------------------------------------------------------------------
  546.   # ◎ 重绘名称背景条
  547.   #--------------------------------------------------------------------------
  548.   def reset_namebar_bitmap
  549.     @namebar_sprite.bitmap.clear                # 重绘之前清理名称背景条
  550.     return if $game_message.face_name.empty? and $game_temp.fuki_noface_name==""  # 无名称时不描绘
  551.     rect = Rect.new(0, 0, 0, 0)
  552.     rect.x = self.x + FUKI::NAME_BAR_X
  553.     rect.y = self.y + 16
  554.     rect.width = self.width - FUKI::NAME_BAR_X * 2
  555.     rect.height = FUKI::FONT_SIZE + 2
  556.     color1 = text_color(FUKI::NAME_BAR_COLOR)
  557.     color2 = text_color(FUKI::NAME_BAR_COLOR)
  558.     color1.alpha = FUKI::NAME_BAR_OPACITY
  559.     color2.alpha = 0
  560.     # 渐变条
  561.     @namebar_sprite.bitmap.gradient_fill_rect(rect, color1, color2)
  562.   end
  563.   #--------------------------------------------------------------------------
  564.   # ◎ 设置窗口背景与位置
  565.   #--------------------------------------------------------------------------
  566.   def reset_window
  567.     self.pause = true
  568.     @background = $game_message.background
  569.     @position = $game_message.position
  570.     if @background == 0   # 普通窗口
  571.       set_opacity(self)   # 透明度设定
  572.     else                  # 背景变暗、透明
  573.       self.opacity = 0
  574.     end
  575.     # 窗口水平居中
  576.     self.x = (544 - self.width) / 2
  577.     case @position
  578.     when 0  # 上
  579.       if FUKI::IN_CONTENT
  580.         self.y = 8
  581.       else
  582.         if FUKI::V_ALIGN == 2
  583.           self.y = [face_height, self.height].max - self.height + 8
  584.         else
  585.           self.y = 8
  586.         end
  587.       end
  588.       @gold_window.y = 360
  589.     when 1  # 中
  590.       self.y = (Graphics.height - self.height) / 2
  591.       @gold_window.y = 0
  592.     when 2  # 下
  593.       if FUKI::V_ALIGN == 0 and face_height > 0
  594.         self.y = \
  595.         Graphics.height - [face_height, self.height].max - self.height*2 - 8
  596.       else
  597.         self.y = Graphics.height - self.height - 8
  598.       end
  599.       @gold_window.y = 0
  600.     end
  601.   end
  602.   #--------------------------------------------------------------------------
  603.   # ◎ 预提取文本
  604.   #--------------------------------------------------------------------------
  605.   def get_message
  606.     text = []
  607.     for i in 0...$game_message.texts.size
  608.       text[i] = ""
  609.       text[i] += "  " if i >= $game_message.choice_start
  610.       text[i] += $game_message.texts[i].clone
  611.       text[i].gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
  612.       text[i].gsub!(/\\V\[([0-9]+)\]/i) { $game_variables[$1.to_i] }
  613.       text[i].gsub!(/\\N\[([0-9]+)\]/i) { $game_actors[$1.to_i].name }
  614.       text[i].gsub!(/\\C\[([0-9]+)\]/i) { "" }
  615.       text[i].gsub!(/\\G/)              { "" }
  616.       text[i].gsub!(/\\\./)             { "" }
  617.       text[i].gsub!(/\\\|/)             { "" }
  618.       text[i].gsub!(/\\!/)              { "" }
  619.       text[i].gsub!(/\\>/)              { "" }
  620.       text[i].gsub!(/\\</)              { "" }
  621.       text[i].gsub!(/\\\^/)             { "" }
  622.       text[i].gsub!(/\\\\/)             { "\\" }
  623.     end
  624.     return text
  625.   end
  626.   #--------------------------------------------------------------------------
  627.   # ◎ 获取窗口尺寸
  628.   #--------------------------------------------------------------------------
  629.   def get_window_size
  630.     contents.font.name = $game_temp.fuki_font_name
  631.     contents.font.size = $game_temp.fuki_font_size
  632.     w = h = 0 # 初始化长宽
  633.     text_con = get_message
  634.     for text in text_con
  635.       x = @contents_x
  636.       loop do
  637.         c = text.slice!(/./m)             # 获取下一个文字
  638.         case c
  639.         when nil                          # 没有可以显示的文字
  640.           break
  641.         else                              # 普通文字
  642.           c_width = contents.text_size(c).width
  643.           x += c_width
  644.         end
  645.       end
  646.       w = [x, w].max
  647.       if $game_message.face_name.empty?
  648.         h = $game_message.texts.size * (FUKI::FONT_SIZE + 2) + 32
  649.       else
  650.         if FUKI::IN_CONTENT
  651.           h_min = face_height + FUKI::FACE_Y_ADJ
  652.           h = [h_min, text_con.size*(FUKI::FONT_SIZE + 2) + 32].max
  653.         else
  654.           h = [48, text_con.size*(FUKI::FONT_SIZE + 2) + 32].max
  655.         end
  656.       end
  657.     end
  658.     # 调整名称显示的高度差
  659.     h += FUKI::NAME_Y_ADJ if @show_name
  660.     # 输入数值的情况
  661.     if $game_message.num_input_variable_id > 0
  662.       w = [w, 24 + $game_message.num_input_digits_max * 16 + face_width].max
  663.       # 预留数值窗口高度
  664.       h += FUKI::FONT_SIZE + 2
  665.       # 避开空对话内容的情况
  666.       h = [h, @number_input_window.height].max
  667.     end
  668.     return w-16, h
  669.   end
  670.   #--------------------------------------------------------------------------
  671.   # ◎ 重设位图容器
  672.   #--------------------------------------------------------------------------
  673.   def reset_contents
  674.     self.contents.dispose
  675.     self.contents = Bitmap.new(self.width - 32, self.height - 32)
  676.   end
  677.   #--------------------------------------------------------------------------
  678.   # ◎ 重设对话框尺寸
  679.   #--------------------------------------------------------------------------
  680.   def reset_msg_size
  681.     size = get_window_size
  682.     self.width = size[0] + 48
  683.     self.height = size[1]
  684.   end
  685.   #--------------------------------------------------------------------------
  686.   # ◎ 重设对话框坐标
  687.   #--------------------------------------------------------------------------
  688.   def reset_msg_pos
  689.     self.pause = false if use_fuki?                  # 关闭暂停标志
  690.     # 调整对话框坐标
  691.     pos = get_character_pos
  692.     case pos
  693.     when nil                                         # 当前屏幕无对话角色时
  694.       @arrow_sprite.visible = false
  695.       reset_window
  696.       unless $game_message.face_name.empty?
  697.         set_face(0)
  698.       end
  699.     else
  700.       # X 坐标
  701.       if pos[0] < 0
  702.         self.x = 0
  703.       elsif pos[0] > Graphics.width - self.width
  704.         self.x = Graphics.width - self.width
  705.       else
  706.         self.x = pos[0]
  707.       end
  708.       # Y 坐标 ◎
  709.       compare = FUKI::IN_CONTENT ? self.height : face_height
  710.       
  711.       if pos[1] < compare
  712.         self.y = pos[1] + self.height + FUKI::MSG_Y_ADJ
  713.         # 调整对话框箭头
  714.         set_arrow(0, pos)
  715.       else
  716.         self.y = pos[1] - pos[2] - FUKI::MSG_Y_ADJ
  717.         # 调整对话框箭头
  718.         set_arrow(1, pos)
  719.       end
  720.     end
  721.     # 调整头像
  722.     unless $game_message.face_name.empty?
  723.       set_face(1)
  724.     # 调整数据输入窗体坐标
  725.     end
  726.     set_input_window(x, y, $game_temp.face_type)
  727.   end
  728.   #--------------------------------------------------------------------------
  729.   # ◎ 调整数值输入
  730.   #     align  : 对齐方式 (1:左 ;0:右)
  731.   #              和头像相反方向
  732.   #--------------------------------------------------------------------------
  733.   def set_input_window(x, y, align)
  734.     return unless @number_input_window.active
  735.     case align
  736.     when 1
  737.       @number_input_window.x = x
  738.       @number_input_window.y = y + @contents_y
  739.     when 0
  740.       @number_input_window.x = x + face_width
  741.       @number_input_window.y = y + @contents_y
  742.     end
  743.     @number_input_window.visible = true
  744.   end
  745.   #--------------------------------------------------------------------------
  746.   # ◎ 调整对话框箭头#######
  747.   #     type : 上下标志 (0: 箭头在上; 1: 箭头在下)
  748.   #     pos    : 坐标数组 (get_character_pos)
  749.   #--------------------------------------------------------------------------
  750.   def set_arrow(type, pos)
  751.     return if pos == nil
  752.     if type == 0
  753.       arrow_name = FUKI::SKIN + "_arrow_up.png"
  754.       @arrow_sprite.bitmap = Cache.system(arrow_name)
  755.       @arrow_sprite.x = pos[0] + (self.width / 2) + FUKI::ARR0W_UP_X_ADJ
  756.       @arrow_sprite.y = self.y - @arrow_sprite.height + FUKI::ARR0W_UP_Y_ADJ
  757.     else
  758.       arrow_name = FUKI::SKIN + "_arrow_down.png"
  759.       @arrow_sprite.bitmap = Cache.system(arrow_name)
  760.       @arrow_sprite.x = pos[0] + (self.width / 2) + FUKI::ARR0W_DOWN_X_ADJ
  761.       @arrow_sprite.y = self.y + self.height + FUKI::ARR0W_DOWN_Y_ADJ
  762.     end
  763.     @arrow_sprite.visible = true
  764.   end
  765.   #--------------------------------------------------------------------------
  766.   # ◎ 调整头像
  767.   #     type  : 头像位置标志 (0:普通对话框 ;1:呼出对话框)
  768.   #--------------------------------------------------------------------------
  769.   def set_face(type)
  770.     case type
  771.     when 0                                    # 普通对话框
  772.       if $game_temp.face_type == 0
  773.         @face_sprite.x = 16
  774.         @face_sprite.mirror = false
  775.       else
  776.         @face_sprite.x = self.width - face_width
  777.         @face_sprite.mirror = true
  778.       end
  779.       @face_sprite.y = self.y + 16
  780.     when 1                                    # 呼出对话框
  781.       # 调整横坐标
  782.       case $game_temp.face_type
  783.       when 0
  784.         @face_sprite.x = self.x + FUKI::FACE_X_ADJ
  785.         @face_sprite.mirror = false
  786.       when 1
  787.         @face_sprite.x = self.x + self.width - face_width - FUKI::FACE_X_ADJ
  788.         @face_sprite.mirror = true
  789.       end
  790.       # 调整纵坐标
  791.       case FUKI::V_ALIGN
  792.       when 0
  793.         @face_sprite.y = self.y
  794.       when 1
  795.         @face_sprite.y = self.y + (self.height - face_height)/2
  796.       when 2
  797.         @face_sprite.y = self.y + self.height - face_height
  798.       end
  799.       @face_sprite.y += FUKI::FACE_Y_ADJ
  800.       # 头像在对话框内的情况
  801.       @face_sprite.y = self.y + FUKI::FACE_Y_ADJ if FUKI::IN_CONTENT
  802.     end
  803.     # 打开头像显示
  804.     @face_sprite.visible = true
  805.   end
  806.   #--------------------------------------------------------------------------
  807.   # ◎ 设定透明名
  808.   #     target : 对象
  809.   #--------------------------------------------------------------------------
  810.   def set_opacity(target)
  811.     target.opacity = FUKI::OPACITY
  812.   end
  813.   #--------------------------------------------------------------------------
  814.   # ◎ 事件是否在屏幕范围内
  815.   #     event : 事件
  816.   #--------------------------------------------------------------------------
  817.   def within_screen_range?(event)
  818.     # 考虑到某些长得比较高的事件
  819.     height = Cache.character(event.character_name).height
  820.     y_plus = event.character_name.include?('!$') ? height/4 : height/8
  821.     range_x = (0..Graphics.width).include?(event.screen_x)
  822.     range_y = (0..Graphics.height + y_plus).include?(event.screen_y)
  823.     return range_x && range_y
  824.   end
  825.   #--------------------------------------------------------------------------
  826.   # ◎ 获取角色坐标
  827.   #--------------------------------------------------------------------------
  828.   def get_character_pos
  829.     # 使用呼出对话框时
  830.    
  831.     if $game_message.face_name.empty? and $game_temp.fuki_noface_name!=""
  832.    
  833.       for event in $game_map.events.values
  834.         next unless within_screen_range?(event)
  835.         if event.name == $game_temp.fuki_noface_name
  836.           x = event.screen_x - (self.width / 2)
  837.           y = event.screen_y - self.height
  838.           height = Cache.character(event.character_name).height
  839.           y_plus = event.character_name.include?('!$') ? height/4 : height/8
  840.           return x, y, y_plus
  841.         end
  842.       end
  843.     end
  844.       
  845.     unless $game_message.face_name.empty? # 待改为@texts判断
  846.       # 事件时
  847.       for event in $game_map.events.values
  848.         next unless within_screen_range?(event)
  849.         if event.name == $game_message.face_name
  850.           x = event.screen_x - (self.width / 2)
  851.           y = event.screen_y - self.height
  852.           height = Cache.character(event.character_name).height
  853.           y_plus = event.character_name.include?('!$') ? height/4 : height/8
  854.           return x, y, y_plus
  855.         end
  856.       end
  857.       # 玩家时
  858.       for member in $game_party.members
  859.         if member.name == $game_message.face_name
  860.           x = $game_player.screen_x - (self.width / 2)
  861.           y = $game_player.screen_y - self.height
  862.           height = Cache.character(member.character_name).height
  863.           y_plus = member.character_name.include?('!$') ? height/4 : height/8
  864.           return x, y, y_plus
  865.         end
  866.       end
  867.     end
  868.     # 无坐标时
  869.     return nil
  870.   end
  871.   #--------------------------------------------------------------------------
  872.   # ◎ 描绘脸谱
  873.   #     face_name  : 脸谱图像文件名
  874.   #     face_index : 脸谱图像索引
  875.   #--------------------------------------------------------------------------
  876.   def draw_fuki_face(face_name, face_index)
  877.     bitmap = Cache.face(face_name)
  878.     width = bitmap.width / 4
  879.     height = bitmap.height / 2
  880.     rect = Rect.new(0, 0, 0, 0)
  881.     rect.x = face_index % 4 * width
  882.     rect.y = face_index / 4 * height
  883.     rect.width = width
  884.     rect.height = height
  885.     @face_sprite.bitmap = Bitmap.new(width, height)
  886.     @face_sprite.bitmap.blt(0, 0, bitmap, rect)
  887.     bitmap.dispose
  888.   end
  889.   #--------------------------------------------------------------------------
  890.   # ● 消息结束
  891.   #--------------------------------------------------------------------------
  892.   def terminate_message
  893.     self.active = false
  894.     @fuki_pause = false
  895.     self.index = -1
  896.     @gold_window.close
  897.     @number_input_window.active = false
  898.     @number_input_window.visible = false
  899.     $game_message.main_proc.call if $game_message.main_proc != nil
  900.     $game_message.clear
  901.     @face_sprite.visible = false
  902.     @update_pos = false                 # 对话框跟随开关关闭
  903.     default_setting                 # 还原默认设定
  904.   end
  905.   #--------------------------------------------------------------------------
  906.   # ◎ 更新消息
  907.   #--------------------------------------------------------------------------
  908.   def update_message
  909.     # 字体设定
  910.     contents.font.name = $game_temp.fuki_font_name
  911.     contents.font.size = $game_temp.fuki_font_size
  912.     contents.font.shadow = FUKI::FONT_SHADOW
  913.     loop do
  914.       c = @text.slice!(/./m)            # 获取下一条文字
  915.       case c
  916.       when nil                          # 没有可以显示的文字
  917.         finish_message                  # 更新结束
  918.         break
  919.       when "\x00"                       # 换行
  920.         # 调整名称显示的高度
  921.         if @show_name
  922.           @show_name = false
  923.           @contents_y += FUKI::NAME_Y_ADJ
  924.         end
  925.         new_line
  926.         if @line_count >= MAX_LINE      # 行数为最大时
  927.           unless @text.empty?           # 如果还有增加则继续
  928.             @fuki_pause = true           # 等待输入
  929.             break
  930.           end
  931.         end
  932.       when "\x01"                       # \C[n]  (更改文字色)
  933.         @text.sub!(/\[([0-9]+)\]/, "")
  934.         contents.font.color = text_color($1.to_i)
  935.         next
  936.       when "\x02"                       # \G  (显示所持金)
  937.         @gold_window.refresh
  938.         @gold_window.open
  939.       when "\x03"                       # \.  (等待 1/4 秒)
  940.         @wait_count = 15
  941.         break
  942.       when "\x04"                       # \|  (等待 1 秒)
  943.         @wait_count = 60
  944.         break
  945.       when "\x05"                       # \!  (等待输入)
  946.         @fuki_pause = true
  947.         break
  948.       when "\x06"                       # \>  (瞬间显示 ON)
  949.         @line_show_fast = true
  950.       when "\x07"                       # \<  (瞬间显示 OFF)
  951.         @line_show_fast = false
  952.       when "\x08"                       # \^  (不等待输入)
  953.         @pause_skip = true
  954.       else                              # 普通文字
  955.         @wait_count = $game_temp.speed  # 对话框打字速度修正
  956.         # 判断头像对文字的影响
  957.         case $game_temp.face_type
  958.         when 0
  959.           contents.draw_text\
  960.           (@contents_x, @contents_y, 40, FUKI::FONT_SIZE + 2, c)
  961.         when 1
  962.           contents.draw_text\
  963.           (@contents_x - face_width, @contents_y, 40, FUKI::FONT_SIZE + 2, c)
  964.         end
  965.         c_width = contents.text_size(c).width
  966.         @contents_x += c_width
  967.       end
  968.       break unless @show_fast or @line_show_fast
  969.     end
  970.   end
  971.   #--------------------------------------------------------------------------
  972.   # ● 消息更新结束
  973.   #--------------------------------------------------------------------------
  974.   def finish_message
  975.     if $game_message.choice_max > 0
  976.       start_choice
  977.     elsif $game_message.num_input_variable_id > 0
  978.       start_number_input
  979.     elsif @pause_skip
  980.       terminate_message
  981.     else
  982.       @fuki_pause = true
  983.     end
  984.     @wait_count = 10
  985.     @text = nil
  986.   end
  987.   #--------------------------------------------------------------------------
  988.   # ● 开始选择项
  989.   #--------------------------------------------------------------------------
  990.   def start_choice
  991.     self.active = true
  992.     self.index = 0
  993.   end
  994.   #--------------------------------------------------------------------------
  995.   # ◎ 开始输入数值
  996.   #--------------------------------------------------------------------------
  997.   def start_number_input
  998.     digits_max = $game_message.num_input_digits_max
  999.     number = $game_variables[$game_message.num_input_variable_id]
  1000.     @number_input_window.digits_max = digits_max
  1001.     @number_input_window.number = number
  1002.     @number_input_window.y = y + @contents_y
  1003.     @number_input_window.active = true
  1004.     @number_input_window.update
  1005.   end
  1006.   #--------------------------------------------------------------------------
  1007.   # ◎ 更新光标
  1008.   #--------------------------------------------------------------------------
  1009.   def update_cursor
  1010.     if @index >= 0
  1011.       # 获取光标的横坐标
  1012.       if $game_message.face_name.empty? or FUKI::H_ALIGN == 1
  1013.         x = 0
  1014.       else
  1015.         x = face_width
  1016.       end
  1017.       # 获取光标的纵坐标
  1018.       y = ($game_message.choice_start + @index) * (FUKI::FONT_SIZE + 2)
  1019.       # 修正名称行
  1020.       unless $game_message.face_name.empty?
  1021.         y += FUKI::NAME_Y_ADJ + FUKI::FONT_SIZE + 2
  1022.       end
  1023.       width = contents.width - face_width
  1024.       self.cursor_rect.set(x, y, width, FUKI::FONT_SIZE + 2)
  1025.     else
  1026.       self.cursor_rect.empty
  1027.     end
  1028.   end
  1029.   #--------------------------------------------------------------------------
  1030.   # ● 文章显示输入处理
  1031.   #--------------------------------------------------------------------------
  1032.   def input_pause
  1033.     if Input.trigger?(Input::B) or Input.trigger?(Input::C)
  1034.       @fuki_pause = false
  1035.       if @text != nil and not @text.empty?
  1036.         new_page if @line_count >= MAX_LINE
  1037.       else
  1038.         terminate_message
  1039.       end
  1040.     end
  1041.   end
  1042.   #--------------------------------------------------------------------------
  1043.   # ● 选择项输入处理
  1044.   #--------------------------------------------------------------------------
  1045.   def input_choice
  1046.     if Input.trigger?(Input::B)
  1047.       if $game_message.choice_cancel_type > 0
  1048.         Sound.play_cancel
  1049.         $game_message.choice_proc.call($game_message.choice_cancel_type - 1)
  1050.         terminate_message
  1051.       end
  1052.     elsif Input.trigger?(Input::C)
  1053.       Sound.play_decision
  1054.       $game_message.choice_proc.call(self.index)
  1055.       terminate_message
  1056.     end
  1057.   end
  1058.   #--------------------------------------------------------------------------
  1059.   # ● 数值输入处理
  1060.   #--------------------------------------------------------------------------
  1061.   def input_number
  1062.     if Input.trigger?(Input::C)
  1063.       Sound.play_decision
  1064.       $game_variables[$game_message.num_input_variable_id] =
  1065.         @number_input_window.number
  1066.       $game_map.need_refresh = true
  1067.       terminate_message
  1068.     end
  1069.   end
  1070. end
复制代码
我通过在游戏中给$game_temp.fuki_noface_name赋值的方式得到事件的坐标,从而使用FUKI对话框。可使用后没有 头像 的对话框显示不出对话框背景,这是怎么回事?跪求一老师指导改错!!!!!!!!!!
作者: 模仿者    时间: 2010-6-23 15:49
你是怎么调用的没说清楚
最好给出你的调用代码
作者: zjlwdwd    时间: 2010-6-23 16:12
本帖最后由 zjlwdwd 于 2010-6-23 16:21 编辑

回复 模仿者 的帖子

  这段代码是在脚本仓库找的。是呼出对话框的脚本。原来的功能大致是这样:1,得到头像图片名称,如果没有图片名称则使用默认对话框。2通过图片名称查找事件,(事件得和图片名一致)得到坐标。如果图上找不到事件,则不显示呼出对话框箭头。按默认坐标显示对话框 3跟据坐标设置呼出对话框。

于是我做了点小修改。在GAME_TEMP类里加了个attr_accessor :fuki_noface_name初使化为“”
对于一些没有头像的人物但地图中又存在该事件想使用称出对话框,于是先给FUKI_NOFACE_NAME手动赋值。即在RM中事件指令列表中在文字之前插入脚本$game_temp.fuki_noface_name="无头像的事件名"
在代码中修改了一小部分。以上就是修改过后的方法。原代码只判断头像图片名称不为空就使用呼出对话框,我修改之后是判断头像名称为空但$Game_temp.fuki_noface_name不为空也使用呼出对话框。但无头像事件显示文字时。呼出对话诓箭头正常显示。坐标也大致正确。却没有对话框背景。我是菜鸟,昨天忙了一夜也没找出原因。因为原代码是别人写的。在具体的调用我也不清楚了
作者: 模仿者    时间: 2010-6-23 17:43
回复 zjlwdwd 的帖子
我试了下 情况是这样

这样算有背景还是没背景?
作者: zjlwdwd    时间: 2010-6-23 18:01
回复 模仿者 的帖子

老师,你怎么做的?告诉我好么?我做的就没背景。而且还不知道错哪···老师!!!!!!!!


   
作者: 模仿者    时间: 2010-6-23 18:02
本帖最后由 模仿者 于 2010-6-23 18:04 编辑

回复 zjlwdwd 的帖子
我就把你的脚本贴到默认工程里 然后事件插入一行脚本
$game_temp.fuki_noface_name="EV001"
再显示文章 其他什么也没做{:nm_3:}
作者: zjlwdwd    时间: 2010-6-23 18:14
本帖最后由 zjlwdwd 于 2010-6-23 18:20 编辑

:funk:但我做的····
作者: wangswz    时间: 2010-6-23 18:19
新建个工程看看是不是别的脚本哪定义重复了
作者: zjlwdwd    时间: 2010-6-24 14:15
:dizzy:新建个工程果然就好了···不过我还是没弄懂其中原由···不过还是先谢谢你们两位了!!呵呵····谢谢!




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1