查看: 10059|回复: 33

[原创发布] 窗口增强系统核心 v1.7 完整更新及范例

[复制链接]

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

发表于 2017-12-3 02:38:18 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

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

×
本帖最后由 SailCat 于 2018-9-7 01:12 编辑

嗯,不仅是移植VA的Window_Base及一些相关内容——
然后加了点私货,然后和XP的默认设定做了一些一致性调整
毕竟是用RGSS1的后台Window类去死命的黑,有些实现方法确实挺绕的
本来想把RGSS3的padding也做上的,结果发现XP写死了16……要做的话只能双窗口,一真的透明背景显示内容,一假的显示背景……太累了,而且Z值没法弄。
为了解放写死的文本行高32,不得不重写了游戏里的所!有!窗口,我也是醉了。于是顺便按VA的继承风格把某些窗口整个重做了。
具体功能呢——见分割定义1的注释部分吧,反正VA VX的皮肤是能直接用了,不会出问题。最好你留一个默认的001-Blue01不然战斗光标就没了
以下是直接使用VA默认皮肤的结果:
1.png
以下用了一个论坛内的VX皮肤,并把行高调整为24
捕获1.PNG

[fold=查看代码][pre lang="ruby"]
#==============================================================================
# ■ 窗口增强系统核心 v1.7 by SailCat
#------------------------------------------------------------------------------
#   方法:本脚本插入到Main之前使用,且需在所有依赖此脚本的其他插件之前
#   依赖:SEP 插件公共核心
#   版本:v1.7 (Build 180907)
#   效果:
#    1. VX、VA格式的皮肤全兼容,直接调用不转换,并对XP的战斗光标做了兼容性处理
#    2. 支持RGSS2的窗口式样,包括边框、底色、平铺+拉伸双背景、色调调整
#    3. 支持RGSS3的窗口开闭效果
#    4. 保留RGSS1的主背景平铺设定,即允许双平铺背景
#    5. 支持窗口快速按屏幕定位的脚本接口,含靠边、移动、缩放功能
#    6. 生成窗口时可以直接指定皮肤文件名,且不受Game_System设定影响
#    7. 无须更改窗口皮肤,可以单独关闭平铺层的背景
#    8. 文字颜色有VX/VA/MV系的32种,而不是XP系的8种,默认颜色与XP保持一致
#    9. 文字行高可调整
#    10.VA风格的血条
#    11.增加了Window_Handler模块,用于处理交互类窗口的消息钩子和按键钩子
#    12.增加了Window_HorzCommand类,用于处理水平排列的命令窗口
#    13.增加了Window_Data类,用于处理游戏数据(物品、特技、武器、防具)列表
#    14.增加了Window_Numeric类,用于处理数值输入的窗口
#    15.追加了大量可以在所有窗口(不仅是对话窗口)中使用的文本控制符
#   配置:有大量配置项,见脚本配置区的具体说明,所有默认设定均为RGSS1的默认值
#   冲突:其他窗口增强脚本和使用默认窗口的自定义界面脚本
#   说明:
#    1. 在不改变配置项的情况下,仅插入本插件并不会对窗口产生任何特殊效果
#    2. 以下窗口的继承关系被调整:
#       Window_Item         从继承Window_Selectable调整为继承Window_Data
#       Window_Skill        从继承Window_Selectable调整为继承Window_Data
#       Window_EquipRight   从继承Window_Selectable调整为继承Window_Data
#       Window_EquipItem    从继承Window_Selectable调整为继承Window_Data
#       Window_ShopCommand  从继承Window_Selectable调整为继承Window_HorzCommand
#       Window_ShopBuy      从继承Window_Selectable调整为继承Window_Data
#       Window_ShopSell     从继承Window_Selectable调整为继承Window_Data
#       Window_ShopNumber   从继承Window_Base      调整为继承Window_Numeric
#       Window_InputNumber  从继承Window_Base      调整为继承Window_Numeric
#       Window_PartyCommand 从继承Window_Selectable调整为继承Window_HorzCommand
#    2. 调整窗口的色调:
#       初始设定:在下面的配置区设定,默认为不改变色调
#       全局调整:使用$game_system.window_tone = Tone.new(r, g, b, gray)
#       个别调整:使用window.tone = Tone.new(r, g, b, gray)
#                 或者window.tone.set(r, g, b, gray)
#    3. 窗口的开闭效果:
#       window.openness = x (x为0-255) 设置打开度,0为完全关,255为完全开
#       window.open或window.close,在相应的Scene的main里调用
#    4. 窗口的位置效果:
#       移动:window.moveto(x, y)           将窗口移动到指定的坐标处
#       缩放:window.resize(width, height)  将窗口的大小更改为指定值
#       对齐:window.align(dir, rect)       将窗口在矩形内按方位对齐
#       靠边:window.dock(other, dir, align)将窗口靠在另一个窗口边上,并对齐
#    5. 交互类窗口的按键和事件挂接:
#       按键:window.set_handler(按键名, method(方法名)),按键为Input系的常量名
#       事件:window.set_handler(事件符号, method(方法名)),事件符号有以下:
#             :index_changed : 选择项改变(仅启用时触发)
#             :visible_changed : 显示/隐藏状态改变(全时触发)
#             :activated : 窗口被启用
#             :deactivated : 窗口被禁用
#             也可自行定义你需要的事件符号
#       取消:window.reset_handler(按键名或事件符号)
#       触发:window.call_handler(自定义事件符号,[方法参数]),按键是自动触发的
#    6. 本插件追加了以下原RGSS1默认对话框没有的控制符:
#       \P[n]   显示队伍中排名第n的角色的名字
#       \E[n]   显示第n号敌人的名字
#       \T[n]   显示敌队中排名第n的敌人的名字
#       \$      显示货币单位
#       \D[?n]  显示第n号游戏数据的名字,当?为:
#          S    特技(带有图标)
#          I    物品(带有图标)
#          W    武器(带有图标)
#          A    防具(带有图标)
#          C    职业
#          B    状态
#          T    图块
#          M    地图
#          E    属性
#          V    事件(本地图内)
#       \I[str] 显示文件名为str的图标
#       \/      人工换行
#       \|      制表位(推进到8字符的倍数)
#       \{      将字体改大6号
#       \}      将字体改小6号
#       \*      开始或者结束文字粗体
#       \_      开始或者结束文字斜体
#       \~      清除格式
#       \:      行首缩进(下一行从此处开始)
#       \`      取消缩进(下一行从头开始)
#       \J[n]   跳至n像素位置
#       \O[n]   将文字不透明度更改为n
#    6. 本插件增强了对话框\v控制符的功能,如下:
#       \V[n]   变换为n号变量的值(原功能),可以嵌套使用
#       \V[Nn.sym] 变换为第n号角色的指定属性值,.sym可为.hp .str之类,下同
#       \V[Pn.sym] 变换为队伍中排名第n的角色的指定属性值
#       \V[En.sym] 变换为第n号敌人的指定属性值
#       \V[Tn.sym] 变换为敌队中排名第n的敌人的指定属性值
#    7. 本插件增强了对话框\c控制符的功能,如下:
#       \C[n]   变换为n号颜色,其中n的取值是0-63
#       \C[#rrggbb] 直接以HTML写法指定颜色,也可写成#rrggbbaa(带透明度)
#       \C[name] 直接以颜色名指定颜色,支持144种颜色名,见下方Color类的常量表
#    8. 所有控制符,大小写不敏感。
#    9. 上述控制符,也可以写在物品、特技、武器、防具的说明中,同样有效。
#==============================================================================
#==============================================================================
# ■ SailCat's 插件公用
#==============================================================================
module SailCat
  $sailcat_import ||= {}
  #--------------------------------------------------------------------------
  # ● 脚本配置区
  #--------------------------------------------------------------------------
  module Window_Config
    STRETCH = true                        # 主背景拉伸(true)/平铺(false)
    TILE_EFFECT = false                   # 开启平铺背景效果
    OPEN_HORZ = false                     # 打开方向,false垂直,true水平
    CLOSE_HORZ = false                    # 关闭方向,false垂直,true水平
    FONT_SIZE_STEP = 6                    # 字体变化步长
    FONT_SIZE_MAX = 64                    # 字体大小上限
    FONT_SIZE_MIN = 10                    # 字体大小下限
    DEFAULT_TONE = Tone.new(0, 0, 0, 0)   # 默认窗口色调
    DISABLED_ALPHA = 128                  # 无效项的透明度
    ICON_WIDTH = 24                       # 图标的宽
    ICON_HEIGHT = 24                      # 图标的高
    ICON_PADDING = 4                      # 图标与正文的间距
    LINE_HEIGHT = 32                      # 文字行高
    ARROW_FOR_VX = "001-Blue01"           # 使用 VX 皮肤时的指定光标皮肤
    CURSOR_PADDING = 32                   # 多列选择窗口光标的间隔
    CURSOR_PADDING_HORZCOMMAND = 32       # 水平命令窗口光标的间隔
    TARGET_SELF_OFFSET_DEFAULT = 10       # 目标窗口选中自己的偏移值,一般不改
    SHOW_GAUGE = false                    # 是否描绘数值槽
    SHOW_SHOP_HINT = false                # 是否显示商店帮助信息
    NUM_KI = Input::SHIFT                 # 数值窗口中千位变化的修饰键
    NUM_MI = Input::CTRL                  # 数值窗口中百万位变化的修饰键
    NUM_BI = Input::ALT                   # 数值窗口中十亿位变化的修饰键
    BACK_OPACITY_DEFAULT = 255            # 总括设置的窗口背景不透明度
    BACK_OPACITY_IN_BATTLE = 160          # 战斗中的窗口背景不透明度
    PALETTE_XP = [                        # 使用 XP 皮肤时的默认调色板
      "#FFFFFF", "#8080FF", "#FF8080", "#80FF80",
      "#80FFFF", "#FF80FF", "#FFFF80", "#C0C0C0", # 基本颜色 0-7
      "#808080", "#2080CC", "#FF3810", "#00A010",
      "#3E9ADE", "#A098FF", "#FFCC20", "#000000", # 扩展颜色 8-15
      "#C0E0FF", "#FFFF40", "#FF4000", "#202040",
      "#E08040", "#E0C040", "#4080C0", "#40C0E0", # 系统颜色 16-23
      "#66CC40", "#C08080", "#20A0D6", "#CCC0FF",
      "#00A040", "#00E060", "#A060E0", "#C080FF"  # 系统颜色 24-31
    ]
    VOCAB_NUM_HINTS = [                   # 数值输入窗口的提示文字
      "←→:±1 ", "↑↓:±10 ", "L/R:±100\n",
      "%s+:x1000倍 ", "", "\n",
      "%s+:x100万倍 ", "", "\n",
      "%s+:x10亿倍", "X:最小", "Z:清零", "Y:最大"
    ]
  end
  #--------------------------------------------------------------------------
  # ● 植入与依赖检查
  #--------------------------------------------------------------------------
  dependency = []
  unless $sailcat_import[:CoreEngine].to_f >= 1.2
    dependency.push "[CoreEngine] SEP 插件公共核心(v1.2以上版本)"
  end
  raise "缺少依赖插件:\n" + dependency.join("\n") unless dependency.empty?
  $sailcat_import[:WindowCore] = 1.5
end

#==============================================================================
# ■ Vocab
#==============================================================================
module Vocab
  include SailCat::Window_Config
  def self.help_text
    @help_text ||= {}
  end
end

#==============================================================================
# ■ Input
#==============================================================================
module Input
  #--------------------------------------------------------------------------
  # ● 获得键名
  #--------------------------------------------------------------------------
  def self.key_name(key)
    constants.each do |name|
      return name if const_get(name) == key
    end
  end
end

#==============================================================================
# ■ String
#==============================================================================
class String
  #--------------------------------------------------------------------------
  # ● 是否含控制符
  #--------------------------------------------------------------------------
  def escaped?;           not self["\\"].nil?;                            end
end

#==============================================================================
# ■ Color
#==============================================================================
class Color
  #--------------------------------------------------------------------------
  # ● 颜色常量
  #--------------------------------------------------------------------------
  ALICEBLUE = Color.html("#F0F8FF")
  ANTIQUEWHITE = Color.html("#FAEBD7")
  AQUA = Color.html("#00FFFF")
  AQUAMARINE = Color.html("#7FFFD4")
  AZURE = Color.html("#F0FFFF")
  BEIGE = Color.html("#F5F5DC")
  BISQUE = Color.html("#FFE4C4")
  BLACK = Color.html("#000000")
  BLANCHEDALMOND = Color.html("#FFEBCD")
  BLUE = Color.html("#0000FF")
  BLUEVIOLET = Color.html("#8A2BE2")
  BROWN = Color.html("#A52A2A")
  BURLYWOOD = Color.html("#DEB887")
  CADETBLUE = Color.html("#5F9EA0")
  CHARTREUSE = Color.html("#7FFF00")
  CHOCOLATE = Color.html("#D2691E")
  CORAL = Color.html("#FF7F50")
  CORNFLOWERBLUE = Color.html("#6495ED")
  CORNSILK = Color.html("#FFF8DC")
  CRIMSON = Color.html("#DC143C")
  CYAN = Color.html("#00FFFF")
  DARKBLUE = Color.html("#00008B")
  DARKCYAN = Color.html("#008B8B")
  DARKGOLDENROD = Color.html("#B8860B")
  DARKGRAY = Color.html("#A9A9A9")
  DARKGREEN = Color.html("#006400")
  DARKKHAKI = Color.html("#BDB76B")
  DARKMAGENTA = Color.html("#8B008B")
  DARKOLIVEGREEN = Color.html("#556B2F")
  DARKORANGE = Color.html("#FF8C00")
  DARKORCHID = Color.html("#9932CC")
  DARKRED = Color.html("#8B0000")
  DARKSALMON = Color.html("#E9967A")
  DARKSEAGREEN = Color.html("#8FBC8F")
  DARKSLATEBLUE = Color.html("#483D8B")
  DARKSLATEGRAY = Color.html("#2F4F4F")
  DARKTURQUOISE = Color.html("#00CED1")
  DARKVIOLET = Color.html("#9400D3")
  DEEPPINK = Color.html("#FF1493")
  DEEPSKYBLUE = Color.html("#00BFFF")
  DIMGRAY = Color.html("#696969")
  DODGERBLUE = Color.html("#1E90FF")
  FELDSPAR = Color.html("#D19275")
  FIREBRICK = Color.html("#B22222")
  FLORALWHITE = Color.html("#FFFAF0")
  FORESTGREEN = Color.html("#228B22")
  FUCHSIA = Color.html("#FF00FF")
  GAINSBORO = Color.html("#DCDCDC")
  GHOSTWHITE = Color.html("#F8F8FF")
  GOLD = Color.html("#FFD700")
  GOLDENROD = Color.html("#DAA520")
  GRAY = Color.html("#808080")
  GREEN = Color.html("#008000")
  GREENYELLOW = Color.html("#ADFF2F")
  HONEYDEW = Color.html("#F0FFF0")
  HOTPINK = Color.html("#FF69B4")
  INDIANRED  = Color.html("#CD5C5C")
  INDIGO  = Color.html("#4B0082")
  IVORY = Color.html("#FFFFF0")
  KHAKI = Color.html("#F0E68C")
  LAVENDER = Color.html("#E6E6FA")
  LAVENDERBLUSH = Color.html("#FFF0F5")
  LAWNGREEN = Color.html("#7CFC00")
  LEMONCHIFFON = Color.html("#FFFACD")
  LIGHTBLUE = Color.html("#ADD8E6")
  LIGHTCORAL = Color.html("#F08080")
  LIGHTCYAN = Color.html("#E0FFFF")
  LIGHTGOLDENRODYELLOW = Color.html("#FAFAD2")
  LIGHTGREY = Color.html("#D3D3D3")
  LIGHTGREEN = Color.html("#90EE90")
  LIGHTPINK = Color.html("#FFB6C1")
  LIGHTSALMON = Color.html("#FFA07A")
  LIGHTSEAGREEN = Color.html("#20B2AA")
  LIGHTSKYBLUE = Color.html("#87CEFA")
  LIGHTSLATEBLUE = Color.html("#8470FF")
  LIGHTSLATEGRAY = Color.html("#778899")
  LIGHTSTEELBLUE = Color.html("#B0C4DE")
  LIGHTYELLOW = Color.html("#FFFFE0")
  LIME = Color.html("#00FF00")
  LIMEGREEN = Color.html("#32CD32")
  LINEN = Color.html("#FAF0E6")
  MAGENTA = Color.html("#FF00FF")
  MAROON = Color.html("#800000")
  MEDIUMAQUAMARINE = Color.html("#66CDAA")
  MEDIUMBLUE = Color.html("#0000CD")
  MEDIUMORCHID = Color.html("#BA55D3")
  MEDIUMPURPLE = Color.html("#9370D8")
  MEDIUMSEAGREEN = Color.html("#3CB371")
  MEDIUMSLATEBLUE = Color.html("#7B68EE")
  MEDIUMSPRINGGREEN = Color.html("#00FA9A")
  MEDIUMTURQUOISE = Color.html("#48D1CC")
  MEDIUMVIOLETRED = Color.html("#C71585")
  MIDNIGHTBLUE = Color.html("#191970")
  MINTCREAM = Color.html("#F5FFFA")
  MISTYROSE = Color.html("#FFE4E1")
  MOCCASIN = Color.html("#FFE4B5")
  NAVAJOWHITE = Color.html("#FFDEAD")
  NAVY = Color.html("#000080")
  OLDLACE = Color.html("#FDF5E6")
  OLIVE = Color.html("#808000")
  OLIVEDRAB = Color.html("#6B8E23")
  ORANGE = Color.html("#FFA500")
  ORANGERED = Color.html("#FF4500")
  ORCHID = Color.html("#DA70D6")
  PALEGOLDENROD = Color.html("#EEE8AA")
  PALEGREEN = Color.html("#98FB98")
  PALETURQUOISE = Color.html("#AFEEEE")
  PALEVIOLETRED = Color.html("#D87093")
  PAPAYAWHIP = Color.html("#FFEFD5")
  PEACHPUFF = Color.html("#FFDAB9")
  PERU = Color.html("#CD853F")
  PINK = Color.html("#FFC0CB")
  PLUM = Color.html("#DDA0DD")
  POWDERBLUE = Color.html("#B0E0E6")
  PURPLE = Color.html("#800080")
  RED = Color.html("#FF0000")
  ROSYBROWN = Color.html("#BC8F8F")
  ROYALBLUE = Color.html("#4169E1")
  SADDLEBROWN = Color.html("#8B4513")
  SALMON = Color.html("#FA8072")
  SANDYBROWN = Color.html("#F4A460")
  SEAGREEN = Color.html("#2E8B57")
  SEASHELL = Color.html("#FFF5EE")
  SIENNA = Color.html("#A0522D")
  SILVER = Color.html("#C0C0C0")
  SKYBLUE = Color.html("#87CEEB")
  SLATEBLUE = Color.html("#6A5ACD")
  SLATEGRAY = Color.html("#708090")
  SNOW = Color.html("#FFFAFA")
  SPRINGGREEN = Color.html("#00FF7F")
  STEELBLUE = Color.html("#4682B4")
  TAN = Color.html("#D2B48C")
  TEAL = Color.html("#008080")
  THISTLE = Color.html("#D8BFD8")
  TOMATO = Color.html("#FF6347")
  TRANSPARENT = Color.html("#00000000")
  TURQUOISE = Color.html("#40E0D0")
  VIOLET = Color.html("#EE82EE")
  VIOLETRED = Color.html("#D02090")
  WHEAT = Color.html("#F5DEB3")
  WHITE = Color.html("#FFFFFF")
  WHITESMOKE = Color.html("#F5F5F5")
  YELLOW = Color.html("#FFFF00")
  YELLOWGREEN = Color.html("#9ACD32")
end

#==============================================================================
# ■ RPG_Cache
#==============================================================================
module RPG
  module Cache
    #--------------------------------------------------------------------------
    # ● 取得图标
    #     filename : 图标文件名
    #     enabled  : 图标有效(彩色)或无效(黑白)
    #--------------------------------------------------------------------------
    def self.icon(filename, enabled = true)
      if enabled
        self.load_bitmap("Graphics/Icons/", filename)
      else
        @disabled ||={}
        key = [filename]
        if (not @disabled.include?(key)) or @disabled[key].disposed?
          @disabled[key] = self.icon(filename, true).to_grayscale
        end
        @disabled[key]         
      end
    end
  end
end

#==============================================================================
# ■ Game_System
#==============================================================================
class Game_System
  include SailCat::Window_Config
  #--------------------------------------------------------------------------
  # ● 取得窗口的色调
  #--------------------------------------------------------------------------
  def window_tone
    # 返回窗口的色调,未设置返回默认值
    @window_tone ||= DEFAULT_TONE
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口的色调
  #     value : 色调值,传入错误的参数不会更改色调
  #--------------------------------------------------------------------------
  def window_tone=(value)
    @window_tone = value if value.is_a?(Tone)
  end
end

#==============================================================================
# ■ Game_Event
#==============================================================================
class Game_Event
  #--------------------------------------------------------------------------
  # ● 事件的名称
  #--------------------------------------------------------------------------
  def name
    @event.name
  end
end

#==============================================================================
# ■ Arrow_Base
#==============================================================================
class Arrow_Base < Sprite
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :index                    # 光标位置
  attr_reader   :help_window              # 帮助窗口
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     viewport : 显示端口
  #--------------------------------------------------------------------------
  def initialize(viewport)
    super(viewport)
    self.bitmap = RPG::Cache.windowskin($game_system.windowskin_name)
    if self.bitmap.width != 192
      self.bitmap = RPG::Cache.windowskin(SailCat::Window_Config::ARROW_FOR_VX)
    end
    self.ox = 16
    self.oy = 64
    self.z = 2500
    @blink_count = 0
    @index = 0
    @help_window = nil
    update
  end
end

#==============================================================================
# ■ Window_Base
#==============================================================================
class Window_Base
  include SailCat::Window_Config
  #--------------------------------------------------------------------------
  # ● 方法重定义
  #--------------------------------------------------------------------------
  unless method_defined?(:sailcat_windowcore_dispose)
    alias sailcat_windowcore_dispose dispose
    alias sailcat_windowcore_back_opacity= back_opacity=
  end
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :tone                     # 窗口的色调
  attr_reader   :openness                 # 窗口的开启程度
  attr_reader   :windowskin_name          # 窗口皮肤 文件名
  attr_accessor :windowskin_fix           # 窗口皮肤 锁定标志
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     x      : 窗口的 X 坐标
  #     y      : 窗口的 Y 坐标
  #     width  : 窗口的宽
  #     height : 窗口的宽
  #     ws_name: 皮肤文件名
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height, ws_name = nil)
    super()
    @windowskin_name = ws_name || $game_system.windowskin_name
    self.windowskin = RPG::Cache.windowskin(@windowskin_name)
    @windowskin_fix = @windowskin_name != $game_system.windowskin_name
    @back_sprite = Sprite.new
    @back_sprite.ox = 0
    @back_sprite.oy = 0
    @tile_sprite = Sprite.new
    @tile_sprite.ox = 0
    @tile_sprite.oy = 0
    @tile_sprite.visible = true
    @openness = 255
    @opening = false
    @closing = false
    @move_duration = 0
    @old_contents = nil
    self.stretch = STRETCH
    self.x = x
    self.y = y
    self.width = width <= 0 ? width + SCREEN_W : width
    self.height = height <= 0 ? height + SCREEN_H : height
    self.z = 100
    self.sailcat_windowcore_back_opacity = 0
    self.back_opacity = BACK_OPACITY_DEFAULT
    self.tone = $game_system.window_tone
    draw_background
    self.tile_effect = TILE_EFFECT
  end
  #--------------------------------------------------------------------------
  # ● 建立内容
  #--------------------------------------------------------------------------
  def create_contents
    contents.dispose if contents
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # ● 单独设置皮肤
  #--------------------------------------------------------------------------
  def windowskin_name=(windowskin_name)
    @windowskin_name = windowskin_name
    @windowskin_fix = true
    self.windowskin = RPG::Cache.windowskin(@windowskin_name)
  end
  #--------------------------------------------------------------------------
  # ● 更新窗口皮肤
  #--------------------------------------------------------------------------
  def windowskin=(ws)
    # 如果是VX的皮肤规格,转为XP格式
    if ws.width == 128 and ws.height == 128
      @vx_skin = true
      b = Bitmap.new(192, 128)
      b.blt(0, 0, ws, Rect.new(0, 0, 64, 128))
      b.blt(128, 0, ws, Rect.new(64, 0, 64, 96))
      b.stretch_blt(Rect.new(152, 24, 16, 8), ws, Rect.new(64, 96, 64, 32))
      ws.dispose
      ws = b
    # 如果是XP的皮肤规格,直接使用
    else
      @vx_skin = false
    end
    super
    unless @tiled_bitmap.nil? or @tiled_bitmap.disposed?
      @tiled_bitmap.dispose
    end
    @tiled_bitmap = Bitmap.new(SCREEN_W - 4, SCREEN_H - 4)
    exp = @vx_skin ? 6 : 7
    for i in 0..(SCREEN_W - 5 >> exp)
      for j in 0..(SCREEN_H - 5 >> exp)
        @tiled_bitmap.blt(i << exp, j << exp, self.windowskin,
          Rect.new(0, 0, 1 << exp, 1 << exp))
      end
    end
    draw_background unless @back_sprite.nil?
  end
  #--------------------------------------------------------------------------
  # ● 更改色调
  #     tone : 窗口的色调
  #--------------------------------------------------------------------------
  def tone=(tone)
    @tone = tone
    @back_sprite.tone = tone
    @tile_sprite.tone = tone
  end
  #--------------------------------------------------------------------------
  # ● 更新窗口打开
  #--------------------------------------------------------------------------
  def update_open
    self.openness += @step_open
    @opening = false if open?
  end
  #--------------------------------------------------------------------------
  # ● 打开判定
  #--------------------------------------------------------------------------
  def open?
    @openness == 255
  end
  #--------------------------------------------------------------------------
  # ● 更新窗口关闭
  #--------------------------------------------------------------------------
  def update_close
    self.openness -= @step_open
    @closing = false if close?
  end
  #--------------------------------------------------------------------------
  # ● 关闭判定
  #--------------------------------------------------------------------------
  def close?
    @openness == 0
  end
  #--------------------------------------------------------------------------
  # ● 打开
  #--------------------------------------------------------------------------
  def open(duration = 6)
    @opening = true unless open?
    @closing = false
    @step_open = (255.0 / [duration, 1].max).ceil
    self
  end
  #--------------------------------------------------------------------------
  # ● 关闭
  #--------------------------------------------------------------------------
  def close(duration = 6)
    @closing = true unless close?
    @opening = false
    @step_open = (255.0 / [duration, 1].max).ceil
    self
  end
  #--------------------------------------------------------------------------
  # ● 显示
  #--------------------------------------------------------------------------
  def show
    self.visible = true
    self
  end
  #--------------------------------------------------------------------------
  # ● 隐藏
  #--------------------------------------------------------------------------
  def hide
    self.visible = false
    self
  end
  #--------------------------------------------------------------------------
  # ● 启用
  #--------------------------------------------------------------------------
  def activate
    self.active = true
    self
  end
  #--------------------------------------------------------------------------
  # ● 禁用
  #--------------------------------------------------------------------------
  def deactivate
    self.active = false
    self
  end
  #--------------------------------------------------------------------------
  # ● 绘制主背景
  #--------------------------------------------------------------------------
  def draw_background
    if stretch
      @back_sprite.bitmap = self.windowskin
      if @vx_skin
        @back_sprite.src_rect = Rect.new(0, 0, 64, 64)
      else
        @back_sprite.src_rect = Rect.new(0, 0, 128, 128)
      end
      @back_sprite.zoom_x = (width - 4) / (@vx_skin ? 64.0 : 128.0)
      @back_sprite.zoom_y = (height - 4) / (@vx_skin ? 64.0 : 128.0)
    else
      @back_sprite.bitmap = @tiled_bitmap
      @back_sprite.src_rect = Rect.new(0, 0, width - 4, height - 4)
      @back_sprite.zoom_x = 1.0
      @back_sprite.zoom_y = 1.0
    end
  end
  #--------------------------------------------------------------------------
  # ● 绘制平铺背景(水印)
  #--------------------------------------------------------------------------
  def draw_tileback
    return if self.tile_effect == false or @scan_bitmap != nil
    if @vx_skin
      @scan_bitmap = Bitmap.new(SCREEN_W - 4, SCREEN_H - 4)
      for i in 0..(SCREEN_W - 5 >> 6)
        for j in 0..(SCREEN_H - 5 >> 6)
          @scan_bitmap.blt(i << 6, j << 6,
            self.windowskin, Rect.new(0, 64, 64, 64))
        end
      end
    else
      @scan_bitmap = Bitmap.new(SCREEN_W - 4, SCREEN_H - 4)
      for i in 0..(SCREEN_H - 5 >> 1)
        @scan_bitmap.fill_rect(0, (i << 1) + 1, SCREEN_W - 4, 1,
          Color.new(5, 5, 5, 40))
      end
    end
    @tile_sprite.bitmap = @scan_bitmap
    @tile_sprite.src_rect = Rect.new(0, 0, width - 4, height - 4)
    @tile_sprite.zoom_x = 1.0
    @tile_sprite.zoom_y = 1.0
  end
  #--------------------------------------------------------------------------
  # ● 释放
  #--------------------------------------------------------------------------
  def dispose
    sailcat_windowcore_dispose
    @back_sprite.dispose
    @tile_sprite.dispose
    @tiled_bitmap.dispose if @tiled_bitmap
    @scan_bitmap.dispose if @scan_bitmap
  end
  #--------------------------------------------------------------------------
  # ● 背景透明度
  #--------------------------------------------------------------------------
  def back_opacity
    return @back_opacity
  end
  #--------------------------------------------------------------------------
  # ● 调整透明度
  #--------------------------------------------------------------------------
  def opacity=(value)
    super
    real_value = value.limit(0, 255) * self.back_opacity / 255
    @back_sprite.opacity = @tile_sprite.opacity = real_value
  end
  #--------------------------------------------------------------------------
  # ● 调整背景透明度
  #--------------------------------------------------------------------------
  def back_opacity=(value)
    @back_opacity = value.limit(0, 255)
    @back_sprite.opacity = @back_opacity * self.opacity / 255
    @tile_sprite.opacity = @back_opacity * self.opacity / 255
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口 X 坐标
  #     x : 新的 X 坐标
  #--------------------------------------------------------------------------
  def x=(x)
    @real_x = x
    super
    @tile_sprite.x = @back_sprite.x = x + 2
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口 Y 坐标
  #     x : 新的 Y 坐标
  #--------------------------------------------------------------------------
  def y=(y)
    @real_y = y
    super
    @tile_sprite.y = @back_sprite.y = y + 2
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口 Z 坐标
  #     z : 新的 Z 坐标
  #--------------------------------------------------------------------------
  def z=(z)
    super
    @tile_sprite.z = @back_sprite.z = z - 1
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口宽度
  #     width : 新的宽度
  #--------------------------------------------------------------------------
  def width=(width)
    @real_width = width
    super
    update_back_size
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口高度
  #     height : 新的高度
  #--------------------------------------------------------------------------
  def height=(height)
    @real_height = height
    super
    update_back_size
  end
  #--------------------------------------------------------------------------
  # ● 取得窗口占用的矩形
  #--------------------------------------------------------------------------
  def rect
    Rect.new(x, y, width, height)
  end
  #--------------------------------------------------------------------------
  # ● 更新背景大小
  #--------------------------------------------------------------------------
  def update_back_size
    if stretch
      @back_sprite.zoom_x = (width - 4) / (@vx_skin ? 64.0 : 128.0)
      @back_sprite.zoom_y = (height - 4) / (@vx_skin ? 64.0 : 128.0)
    else
      @back_sprite.src_rect = Rect.new(0, 0, width - 4, height - 4)
    end
    @tile_sprite.src_rect = Rect.new(0, 0, width - 4, height - 4)
  end
  #--------------------------------------------------------------------------
  # ● 重设窗口大小
  #     width    : 新的宽度
  #     height   : 新的高度
  #     duration : 重设效果持续时间
  #--------------------------------------------------------------------------
  def resize(width, height, duration = 0)
    move(self.x, self.y, width, height, duration)
    self
  end
  #--------------------------------------------------------------------------
  # ● 移动窗口位置
  #     x        : 新的 X 坐标
  #     y        : 新的 Y 坐标
  #     duration : 重设效果持续时间
  #--------------------------------------------------------------------------
  def moveto(x, y, duration = 0)
    move(x, y, self.width, self.height, duration)
    self
  end
  #--------------------------------------------------------------------------
  # ● 窗口居中
  #     rect : 居中的参考矩形
  #--------------------------------------------------------------------------
  def center(rect = Rect.new(0, 0, SCREEN_W, SCREEN_H))
    moveto(rect.x + (rect.width - self.width >> 1),
      rect.y + (rect.height - self.height >> 1))
    self
  end
  #--------------------------------------------------------------------------
  # ● 窗口对齐
  #     d : 对齐方向(1-9)
  #     rect : 对齐的参考矩形
  #--------------------------------------------------------------------------
  def align(d, rect = Rect.new(0, 0, SCREEN_W, SCREEN_H))
    self.x = rect.x + ((rect.width - self.width) * ((d - 1) % 3) >> 1)
    self.y = rect.y + ((rect.height - self.height) * (2 - (d - 1) / 3) >> 1)
    self
  end
  #--------------------------------------------------------------------------
  # ● 窗口贴合
  #     other : 被贴合的另一窗口
  #     d     : 贴合方向(2/4/6/8)
  #     a     : 对齐方向(2=>1/2/3, 4=>1/4/7, 6=>3/6/9, 8=>7/8/9)
  #--------------------------------------------------------------------------
  def dock(other, d, a = d)
    rect = other.rect
    case d
    when 2, 8
      self.x = rect.x + ((rect.width - self.width) * ((a - 1) % 3) >> 1)
      self.y = d == 2 ? rect.top - self.height : rect.bottom
    when 4, 6
      self.x = d == 4 ? rect.right : rect.left - self.width
      self.y = rect.y + ((rect.height - self.height) * (2 - (a - 1) / 3) >> 1)
    end
    self
  end
  #--------------------------------------------------------------------------
  # ● 执行移动窗口
  #--------------------------------------------------------------------------
  def move(x, y, width = nil, height = nil, duration = 0)
    return if moving?
    width ||= self.width
    height ||= self.height
    return if x == self.x and y == self.y and
      width == self.width and height == self.height
    if duration == 0
      self.x = x
      self.y = y
      self.width = width
      self.height = height
      return
    end
    @move_duration = duration
    @step_x = (x - @real_x) * 1.0 / @move_duration
    @step_y = (y - @real_y) * 1.0 / @move_duration
    @step_width = (width - @real_width) * 1.0 / @move_duration
    @step_height = (height - @real_height) * 1.0 / @move_duration
    @real_x = x
    @real_y = y
    @real_width = width
    @real_height = height
    if self.width != width or self.height != height
      @old_contents = contents.clone
    end
    self
  end
  #--------------------------------------------------------------------------
  # ● 移动中判定
  #--------------------------------------------------------------------------
  def moving?
    @move_duration > 0
  end
  #--------------------------------------------------------------------------
  # ● 更新移动窗口
  #--------------------------------------------------------------------------
  def update_move
    @move_duration -= 1 if @move_duration > 0
    last_x = @real_x
    last_y = @real_y
    last_width = @real_width
    last_height = @real_height
    self.x = last_x - Integer(@step_x * @move_duration)
    self.y = last_y - Integer(@step_y * @move_duration)
    self.width = last_width - Integer(@step_width * @move_duration)
    self.height = last_height - Integer(@step_height * @move_duration)
    if self.width != last_width or self.height != last_height
      create_contents
      contents.blt(0, 0, @old_contents, Rect.new(0, 0, width, height))
    end
    @real_x = last_x
    @real_y = last_y
    @real_width = last_width
    @real_height = last_height
    if @old_contents != nil and @move_duration == 0
      @old_contents.dispose
      @old_contents = nil
    end
  end
  #--------------------------------------------------------------------------
  # ● 改变窗口可视性
  #     visible : 新的可视性
  #--------------------------------------------------------------------------
  def visible=(visible)
    super
    @back_sprite.visible = visible
    @tile_sprite.visible = visible
  end
  #--------------------------------------------------------------------------
  # ● 改变窗口背景绘制方式
  #     stretch : 新的绘制方式(平铺/拉伸)
  #--------------------------------------------------------------------------
  def stretch=(stretch)
    if stretch != self.stretch
      super
      @back_sprite.bitmap.dispose if stretch
      draw_background
    end
  end
  #--------------------------------------------------------------------------
  # ● 改变窗口开放度
  #--------------------------------------------------------------------------
  def openness=(openness)
    last_x = @real_x
    last_y = @real_y
    last_w = @real_width
    last_h = @real_height
    dir = (@openness > openness ? CLOSE_HORZ : OPEN_HORZ)
    # 设置开放度
    @openness = openness.limit(0, 255)
    # 非完全打开时,隐藏内容
    if @openness > 0 and self.contents
      self.contents_opacity = 0
      @old_contents = self.contents.clone
      self.contents.dispose
      self.contents = nil
    end
    # 水平打开/关闭
    if dir
      self.x = last_x + (last_w >> 1) * (255 - @openness) / 255
      self.width = last_w * @openness / 255
      @real_x = last_x
      @real_width = last_w
    # 垂直打开/关闭
    else
      self.y = last_y + (last_h >> 1) * (255 - @openness) / 255
      self.height = last_h * @openness / 255
      @real_y = last_y
      @real_height = last_h
    end
    # 仅完全打开时显示内容
    if open?
      self.contents ||= @old_contents || create_contents
      self.contents_opacity = 255
      @old_contents = nil
    end
  end
  #--------------------------------------------------------------------------
  # ● 是否显示水印
  #--------------------------------------------------------------------------
  def tile_effect
    @tile_sprite.visible
  end
  #--------------------------------------------------------------------------
  # ● 设置是否显示水印
  #     tile_effect : 是否显示水印(true/false)
  #--------------------------------------------------------------------------
  def tile_effect=(tile_effect)
    @tile_sprite.visible = tile_effect
    draw_tileback
  end
  #--------------------------------------------------------------------------
  # ● 更新
  #--------------------------------------------------------------------------
  def update
    super
    # 如果窗口的外观被变更了、再设置
    if $game_system.windowskin_name != @windowskin_name and not @windowskin_fix
      @windowskin_name = $game_system.windowskin_name
      self.windowskin = RPG::Cache.windowskin(@windowskin_name)
    end
    update_open if @opening
    update_close if @closing
    update_move if moving?
  end
  #--------------------------------------------------------------------------
  # ● 皮肤内是否含有调色板
  #--------------------------------------------------------------------------
  def skin_has_palette?
    @vx_skin || windowskin.get_pixel(152, 24).alpha > 0
  end
  #--------------------------------------------------------------------------
  # ● 取得颜色
  #     n     : 颜色索引(0-63)
  #     alpha : 强制指定不透明度(0-255)
  #--------------------------------------------------------------------------
  def text_color(n, alpha = nil)
    i = n & 31
    alpha = (alpha || 255) * DISABLED_ALPHA / 255 if n >= 31
    if skin_has_palette?
      c = windowskin.get_pixel(152 + ((i & 7) << 1), 24 + ((i & 24) >> 2))
    else
      v = PALETTE_XP[n & 31]
      c = v ? Color.html(v) : Color.new(255, 255, 255, 255)
    end
    c.alpha = alpha if alpha
    return c
  end
  #--------------------------------------------------------------------------
  # ● 取得特殊文字色
  #--------------------------------------------------------------------------
  def normal_color;      text_color(0);   end;    # 普通文字色
  def system_color;      text_color(16);  end;    # 系统文字色
  def crisis_color;      text_color(17);  end;    # 危机文字色
  def knockout_color;    text_color(18);  end;    # 战斗不能文字色
  def gauge_back_color;  text_color(19);  end;    # 数值槽背景色
  def hp_gauge_color1;   text_color(20);  end;    # HP 槽颜色1
  def hp_gauge_color2;   text_color(21);  end;    # HP 槽颜色2
  def sp_gauge_color1;   text_color(22);  end;    # SP 槽颜色1
  def sp_gauge_color2;   text_color(23);  end;    # SP 槽颜色2
  def sp_cost_color;     text_color(23);  end;    # SP 消费色
  def power_up_color;    text_color(24);  end;    # 数值上升比较色
  def power_down_color;  text_color(25);  end;    # 数值下降比较色
  def exp_gauge_color1;  text_color(28);  end;    # EXP 槽颜色1
  def exp_gauge_color2;  text_color(29);  end;    # EXP 槽颜色2
  def disabled_color;    text_color(32);  end;    # 无效文字色
  #--------------------------------------------------------------------------
  # ● 取得变化值颜色
  #--------------------------------------------------------------------------
  def param_change_color(change)
    return power_up_color   if change > 0
    return power_down_color if change < 0
    return normal_color
  end
  #--------------------------------------------------------------------------
  # ● 取得HTML颜色
  #     str : HTML颜色值
  #--------------------------------------------------------------------------
  def html_color(str)
    if str[0] == ?#
      Color.html(str) rescue normal_color
    else
      Color.const_get(str.upcase) rescue normal_color
    end
  end
  #--------------------------------------------------------------------------
  # ● 取得行高
  #     lines : 行数
  #--------------------------------------------------------------------------
  def line_height(lines = 1)
    return LINE_HEIGHT * lines
  end
  #--------------------------------------------------------------------------
  # ● 取得容纳指定行数的窗口高
  #     lines : 行数
  #--------------------------------------------------------------------------
  def window_h(lines = 1)
    return line_height(lines) + 32
  end
  #--------------------------------------------------------------------------
  # ● 更改文字颜色
  #     enabled : 颜色是否为无效状态
  #--------------------------------------------------------------------------
  def change_color(color, enabled = true)
    contents.font.color = color
    contents.font.color.alpha = DISABLED_ALPHA unless enabled
  end
  #--------------------------------------------------------------------------
  # ● 绘制文字(与Bitmap调用方法相同)
  #--------------------------------------------------------------------------
  def draw_text(*args)
    contents.draw_text(*args)
  end
  #--------------------------------------------------------------------------
  # ● 取得文字尺寸矩形(与Bitmap调用方法相同)
  #--------------------------------------------------------------------------
  def text_size(str)
    contents.text_size(str.to_s)
  end
  #--------------------------------------------------------------------------
  # ● 绘制带有控制符的文字
  #--------------------------------------------------------------------------
  def draw_text_ex(x, y, text)
    reset_font_settings
    text = convert_escape_characters(text)
    pos = [x, y, x, calc_line_height(text)]
    process_character(text.slice!(/./m), text, pos) until text.empty?
  end
  #--------------------------------------------------------------------------
  # ● 重设字体
  #--------------------------------------------------------------------------
  def reset_font_settings(keep_color = false)
    change_color(normal_color) unless keep_color
    contents.font.size = Font.default_size
    contents.font.bold = Font.default_bold
    contents.font.italic = Font.default_italic
  end
  #--------------------------------------------------------------------------
  # ● 变换控制符
  #--------------------------------------------------------------------------
  def convert_escape_characters(text)
    result = text.to_s.clone
    result.gsub!(/\\/)              { "\e" }
    result.gsub!(/\e\e/)            { "\\" }
    result.gsub!(/\e\//)            { "\n" }
    result.gsub!(/\e\|/)            { "\t" }
    begin
      last_result = result.clone
      result.gsub!(/\eV\[(\d+)\]/i) { $game_variables[$1.to_i] }
    end until last_result == result
    result.gsub!(/\eV\[N(\d+)\.(\w+)\]/i)  { battler_param(0, $1.to_i, $2) }
    result.gsub!(/\eV\[P(\d+)\.(\w+)\]/i)  { battler_param(1, $1.to_i, $2) }
    result.gsub!(/\eV\[E(\d+)\.(\w+)\]/i)  { battler_param(2, $1.to_i, $2) }
    result.gsub!(/\eV\[T(\d+)\.(\w+)\]/i)  { battler_param(3, $1.to_i, $2) }
    result.gsub!(/\eD\[S(\d+)\]/i)  { item_name($data_skills,  $1.to_i) }
    result.gsub!(/\eD\[I(\d+)\]/i)  { item_name($data_items,   $1.to_i) }
    result.gsub!(/\eD\[W(\d+)\]/i)  { item_name($data_weapons, $1.to_i) }
    result.gsub!(/\eD\[A(\d+)\]/i)  { item_name($data_armors,  $1.to_i) }
    result.gsub!(/\eD\[C(\d+)\]/i)  { data_name(0, $1.to_i) }
    result.gsub!(/\eD\[B(\d+)\]/i)  { data_name(1, $1.to_i) }
    result.gsub!(/\eD\[T(\d+)\]/i)  { data_name(2, $1.to_i) }
    result.gsub!(/\eD\[M(\d+)\]/i)  { data_name(3, $1.to_i) }
    result.gsub!(/\eD\[E(\d+)\]/i)  { data_name(4, $1.to_i) }
    result.gsub!(/\eD\[V(\d+)\]/i)  { event_name($1.to_i) }
    result.gsub!(/\eN\[(\d+)\]/i)   { actor_name($1.to_i) }
    result.gsub!(/\eP\[(\d+)\]/i)   { party_member_name($1.to_i) }
    result.gsub!(/\eE\[(\d+)\]/i)   { enemy_name($1.to_i) }
    result.gsub!(/\eT\[(\d+)\]/i)   { troop_member_name($1.to_i) }
    result.gsub!(/\e\$/)            { Vocab.gold }
    result
  end
  #--------------------------------------------------------------------------
  # ● 物品的名称
  #--------------------------------------------------------------------------
  def item_name(catalog, n)
    item = catalog[n]
    item ? "\eI[#{item.icon_name}]#{item.name}" : ""
  end
  #--------------------------------------------------------------------------
  # ● 数据的名称
  #--------------------------------------------------------------------------
  def data_name(type, n)
    case type
    when 0
      get_name($data_classes[n])
    when 1
      get_name($data_states[n])
    when 2
      get_name($data_tilesets[n])
    when 3
      $data_mapinfos ||= load_data("Data/MapInfos.rxdata")
      n = $game_map.map_id if n == 0
      get_name($data_mapinfos[n])
    when 4
      $data_system.elements[n] || ""
    end
  end
  #--------------------------------------------------------------------------
  # ● 获得名称
  #--------------------------------------------------------------------------
  def get_name(object)
    object ? object.name : ""
  end
  #--------------------------------------------------------------------------
  # ● 事件的名称
  #--------------------------------------------------------------------------
  def event_name(n)
    $game_map ? get_name($game_system.map_interpreter.get_character(n)) : ""
  end
  #--------------------------------------------------------------------------
  # ● 角色的名称
  #--------------------------------------------------------------------------
  def actor_name(n)
    n >= 1 ? get_name($game_actors[n]) : ""
  end
  #--------------------------------------------------------------------------
  # ● 队伍顺序角色的名称
  #--------------------------------------------------------------------------
  def party_member_name(n)
    n >= 1 ? get_name($game_party.actors[n - 1]) : ""
  end
  #--------------------------------------------------------------------------
  # ● 敌人的名称
  #--------------------------------------------------------------------------
  def enemy_name(n)
    n >= 1 ? get_name($data_enemies[n]) : ""
  end
  #--------------------------------------------------------------------------
  # ● 队伍顺序敌人的名称
  #--------------------------------------------------------------------------
  def troop_member_name(n)
    n >= 1 ? get_name($game_troop.enemies[n - 1]) : ""
  end
  #--------------------------------------------------------------------------
  # ● 战斗者的指数
  #--------------------------------------------------------------------------
  def battler_param(type, n, param)
    case type
    when 0
      battler = $game_actors[n]
    when 1
      battler = n >= 1 ? $game_party.actors[n - 1] : nil
    when 2
      battler = $data_enemies[n]
    when 3
      battler = n >= 1 ? $game_troop.enemies[n - 1] : nil
    end
    battler ? (battler.send(param.downcase) rescue 0) : 0
  end
  #--------------------------------------------------------------------------
  # ● 逐字符解析
  #     c    : 字符
  #     text : 剩余的文字
  #     pos  : 绘制位置
  #--------------------------------------------------------------------------
  def process_character(c, text, pos)
    case c
    when "\n"   # 折行
      process_new_line(text, pos)
    when "\f"   # 折页
      process_new_page(text, pos)
    when "\t"   # 制表位
      process_tab_stop(text, pos)
    when "\e"   # 控制字符
      process_escape_character(obtain_escape_code(text), text, pos)
    else        # 普通字符
      process_normal_character(c, pos)
    end
  end
  #--------------------------------------------------------------------------
  # ● 绘制下一个普通字符
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    text_width = text_size(c).width
    draw_text(pos[0], pos[1], text_width << 1, pos[3], c)
    pos[0] += text_width
  end
  #--------------------------------------------------------------------------
  # ● 折行处理
  #--------------------------------------------------------------------------
  def process_new_line(text, pos)
    pos[0] = pos[2]
    pos[1] += pos[3]
    pos[3] = calc_line_height(text)
  end
  #--------------------------------------------------------------------------
  # ● 折页处理
  #--------------------------------------------------------------------------
  def process_new_page(text, pos)
  end
  #--------------------------------------------------------------------------
  # ● 制表位处理
  #--------------------------------------------------------------------------
  def process_tab_stop(text, pos)
    tab_width = text_size(" ").width << 3
    pos[0] = (pos[0] / tab_width + 1) * tab_width
  end
  #--------------------------------------------------------------------------
  # ● 获得控制符
  #--------------------------------------------------------------------------
  def obtain_escape_code(text)
    text.slice!(/^[\040-\176]/i)
  end
  #--------------------------------------------------------------------------
  # ● 获得控制符参数值
  #--------------------------------------------------------------------------
  def obtain_escape_param(text)
    text.slice!(/^\[[^\133-\135]+\]/)[/[^\133-\135]+/] rescue ""
  end
  #--------------------------------------------------------------------------
  # ● 处理控制字符
  #     code : 控制命令符
  #--------------------------------------------------------------------------
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'C'
      param = obtain_escape_param(text)
      change_color(param[/^\d+$/] ? text_color(param.to_i) : html_color(param))
    when 'O'
      param = obtain_escape_param(text)
      contents.font.color.alpha = param[/^\d+$/] ? param.to_f : 255.0
    when 'I'
      process_draw_icon(obtain_escape_param(text), pos)
    when 'J'
      param = obtain_escape_param(text)
      pos[0] = param.to_i if param[/^\d+$/]
    when '{'
      make_font_bigger
    when '}'
      make_font_smaller
    when '*'
      make_font_bold
    when '_'
      make_font_italic
    when '~'
      reset_font_settings
    when ':'
      pos[2] = pos[0]
    when '`'
      pos[2] = 0
    end
  end
  #--------------------------------------------------------------------------
  # ● 绘画图标
  #--------------------------------------------------------------------------
  def process_draw_icon(icon_name, pos)
    draw_icon(icon_name, pos[0] + ICON_PADDING, pos[1], true, pos[3])
    pos[0] += ICON_WIDTH + (ICON_PADDING << 1)
  end
  #--------------------------------------------------------------------------
  # ● 增大字体
  #--------------------------------------------------------------------------
  def make_font_bigger
    contents.font.size += FONT_SIZE_STEP if contents.font.size < FONT_SIZE_MAX
  end
  #--------------------------------------------------------------------------
  # ● 缩小字体
  #--------------------------------------------------------------------------
  def make_font_smaller
    contents.font.size -= FONT_SIZE_STEP if contents.font.size > FONT_SIZE_MIN
  end
  #--------------------------------------------------------------------------
  # ● 加粗字体
  #--------------------------------------------------------------------------
  def make_font_bold
    contents.font.bold = !contents.font.bold
  end
  #--------------------------------------------------------------------------
  # ● 倾斜字体
  #--------------------------------------------------------------------------
  def make_font_italic
    contents.font.italic = !contents.font.italic
  end
  #--------------------------------------------------------------------------
  # ● 计算行高
  #     restore_font_size : 计算后恢复原字体大小
  #--------------------------------------------------------------------------
  def calc_line_height(text, restore_font_size = true)
    result = [line_height, contents.font.size].max
    last_font_size = contents.font.size
    text.slice(/^.*$/).scan(/\e[\{\}~]/).each do |esc|
      make_font_bigger  if esc == "\e{"
      make_font_smaller if esc == "\e}"
      contents.font.size = Font.default_size if esc == "\e~"
      result = [result, contents.font.size].max
    end
    contents.font.size = last_font_size if restore_font_size
    result
  end
  #--------------------------------------------------------------------------
  # ● 计算列宽
  #     restore_font_size : 计算后恢复原字体大小
  #--------------------------------------------------------------------------
  def calc_text_width(text, restore_font_size = true)
    last_font_size = contents.font.size
    last_font_bold = contents.font.bold
    last_font_italic = contents.font.italic
    result = col_width = 0
    esc = false
    text.scan(/^.*$/).each do |line|
      filter_escape_char(line)
      line.scan(/./).each do |char|
        case char
        when "\t"
          tab_width = text_size(" ").width << 3
          col_width = (col_width / tab_width + 1) * tab_width if col_width > 0
        when "\e"
          esc = true
        else
          if esc
            col_width += calc_escape_width(char)
            esc = false
          else
            col_width += text_size(char).width
          end
        end
      end
      result = [result, col_width].max
    end
    if restore_font_size
      contents.font.size = last_font_size
      contents.font.bold = last_font_bold
      contents.font.italic = last_font_italic
    end
    result
  end
  #--------------------------------------------------------------------------
  # ● 过滤控制符
  #     line : 行文字
  #--------------------------------------------------------------------------
  def filter_escape_char(line)
    line.gsub!(/\e[CO]\[[^\133-\135]+\]/i) { "" }
    line.gsub!(/\eI\[[^\133-\135]+\]/i) { "\eI"}
  end
  #--------------------------------------------------------------------------
  # ● 计算控制符所占宽度
  #     char : 控制符
  #--------------------------------------------------------------------------
  def calc_escape_width(char)
    make_font_bigger  if char == "{"
    make_font_smaller if char == "}"
    make_font_bold if char == "*"
    make_font_italic if char == "_"
    reset_font_settings(true) if char == "~"
    return ICON_WIDTH + (ICON_PADDING << 1) if char == "I"
    0
  end
  #--------------------------------------------------------------------------
  # ● 绘制值槽
  #     rate   : 比例
  #     color1 : 左侧颜色
  #     color2 : 右侧颜色
  #--------------------------------------------------------------------------
  def draw_gauge(x, y, width, rate, color1, color2)
    return unless SHOW_GAUGE
    fill_w = (width * rate).to_i
    gauge_y = y + line_height - 8
    contents.fill_rect(x, gauge_y, width, 6, gauge_back_color)
    contents.gradient_fill_rect(x, gauge_y, fill_w, 6, color1, color2)
  end
  #--------------------------------------------------------------------------
  # ● 绘制图标
  #--------------------------------------------------------------------------
  def draw_icon(icon_name, x, y, enabled = true, line = line_height)
    bitmap = RPG::Cache.icon(icon_name, enabled)
    rect = Rect.new(0, 0, ICON_WIDTH, ICON_HEIGHT)
    height = [line, contents.font.size].max
    oy = [(height - ICON_HEIGHT) >> 1, 0].max
    contents.blt(x, y + oy, bitmap, rect, enabled ? 255 : DISABLED_ALPHA)
  end
  #--------------------------------------------------------------------------
  # ● 取得HP的颜色
  #--------------------------------------------------------------------------
  def hp_color(actor)
    return knockout_color if actor.hp == 0
    return crisis_color if actor.hp < actor.maxhp >> 2
    return normal_color
  end
  #--------------------------------------------------------------------------
  # ● 取得SP的颜色
  #--------------------------------------------------------------------------
  def sp_color(actor)
    return crisis_color if actor.sp < actor.maxsp >> 2
    return normal_color
  end
  #--------------------------------------------------------------------------
  # ● 取得EXP的颜色
  #--------------------------------------------------------------------------
  def exp_color(actor)
    return normal_color
  end
  #--------------------------------------------------------------------------
  # ● 名称的描绘
  #     actor : 角色
  #     x     : 描画目标 X 坐标
  #     y     : 描画目标 Y 坐标
  #     width : 描画目标宽度
  #--------------------------------------------------------------------------
  def draw_actor_name(actor, x, y, width = 120)
    change_color(normal_color)
    draw_text(x, y, width, line_height, actor.name)
  end
  #--------------------------------------------------------------------------
  # ● 职业的描绘
  #--------------------------------------------------------------------------
  def draw_actor_class(actor, x, y, width = 236)
    change_color(normal_color)
    draw_text(x, y, width, line_height, actor.class_name)
  end
  #--------------------------------------------------------------------------
  # ● 等级的描绘
  #--------------------------------------------------------------------------
  def draw_actor_level(actor, x, y)
    change_color(system_color)
    draw_text(x, y, 32, line_height, Vocab.level_a)
    change_color(normal_color)
    draw_text(x + 32, y, 24, line_height, actor.level.to_s, 2)
  end
  #--------------------------------------------------------------------------
  # ● 描绘状态
  #--------------------------------------------------------------------------
  def draw_actor_state(actor, x, y, width = 120, always = true)
    text = make_battler_state_text(actor, width, always)
    change_color(actor.hp == 0 ? knockout_color : normal_color)
    draw_text(x, y, width, line_height, text)
  end
  #--------------------------------------------------------------------------
  # ● 描绘当前和最大值
  #     current : 当前值
  #     max     : 最大值
  #     color1  : 当前值颜色
  #     color2  : 最大值颜色
  #--------------------------------------------------------------------------
  def draw_current_and_max_values(x, y, width, current, max, color1, color2)
    change_color(color1)
    half = (width - 12) >> 1
    if half < text_size(max).width
      draw_text(x, y, width, line_height, current, 2)
    else
      draw_text(x, y, half, line_height, current, 2)
      change_color(color2)
      draw_text(x + half, y, 12, line_height, "/", 1)
      draw_text(x + half + 12, y, half, line_height, max, 0)
    end
  end
  #--------------------------------------------------------------------------
  # ● 描绘 EXP
  #--------------------------------------------------------------------------
  def draw_actor_exp(actor, x, y, width = 204)
    draw_gauge(x, y, width, actor.exp_rate, exp_gauge_color1, exp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 24, line_height, Vocab.exp_a)
    draw_current_and_max_values(x + 24, y, width - 24, actor.exp_s,
      actor.next_exp_s, normal_color, normal_color)
  end
  #--------------------------------------------------------------------------
  # ● 描绘 HP
  #--------------------------------------------------------------------------
  def draw_actor_hp(actor, x, y, width = 144)
    draw_gauge(x, y, width, actor.hp_rate, hp_gauge_color1, hp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 32, line_height, Vocab.hp)
    draw_current_and_max_values(x + 32, y, width - 32, actor.hp, actor.maxhp,
      hp_color(actor), normal_color)
  end
  #--------------------------------------------------------------------------
  # ● 描绘 SP
  #--------------------------------------------------------------------------
  def draw_actor_sp(actor, x, y, width = 144)
    draw_gauge(x, y, width, actor.sp_rate, sp_gauge_color1, sp_gauge_color2)
    change_color(system_color)
    draw_text(x, y, 32, line_height, Vocab.sp)
    draw_current_and_max_values(x + 32, y, width - 32, actor.sp, actor.maxsp,
      sp_color(actor), normal_color)
  end
  #--------------------------------------------------------------------------
  # ● 描画数值键对
  #     key  : 数值键名
  #     value: 数值
  #     ref  : 参考数值
  #--------------------------------------------------------------------------
  def draw_key_value_pair(x, y, key, value, ref = nil, width = 136)
    key_width = text_size(key).width + 8
    change_color(system_color)
    draw_text(x, y, key_width, line_height, key)
    change_color(param_change_color(value - (ref || value)))
    draw_text(x + key_width, y, width - key_width, line_height, value.to_s, 2)
  end
  #--------------------------------------------------------------------------
  # ● 描绘能力值
  #     type  : 能力值种类 (0~6)
  #--------------------------------------------------------------------------
  def draw_actor_parameter(actor, x, y, type, width = 156)
    symbol = [:atk, :pdef, :mdef, :str, :dex, :agi, :int][type]
    parameter_name = Vocab.send(symbol)
    parameter_value = actor.send(symbol)
    draw_key_value_pair(x, y, parameter_name, parameter_value, nil, width)
  end
  #--------------------------------------------------------------------------
  # ● 描绘物品名
  #     item : 物品
  #     enabled : 是否可用
  #--------------------------------------------------------------------------
  def draw_item_name(item, x, y, enabled = true, width = 240)
    return unless item
    draw_icon(item.icon_name, x, y, enabled)
    change_color(normal_color, enabled)
    x += ICON_WIDTH + ICON_PADDING
    draw_text(x, y, width - ICON_WIDTH - ICON_PADDING, line_height, item.name)
  end
  #--------------------------------------------------------------------------
  # ● 描绘金钱数目
  #--------------------------------------------------------------------------
  def draw_currency_value(value, unit, x, y, width)
    cx = text_size(unit).width
    change_color(normal_color)
    draw_text(x, y, width - cx - 2, line_height, value, 2)
    change_color(system_color)
    draw_text(x, y, width, line_height, unit, 2)
  end
end

#==============================================================================
# ■ Window_Handler
#------------------------------------------------------------------------------
#  窗口的激活和按键事件处理模块,被Window_Selectable和Window_Numeric共同引用。
#==============================================================================
module Window_Handler
  include Input
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :handler                  # 按键/事件处理钩子
  #--------------------------------------------------------------------------
  # ● 注入按键/事件处理
  #--------------------------------------------------------------------------
  def set_handler(key, method)
    method ? @handler[key] = method : reset_handler(key)
  end
  #--------------------------------------------------------------------------
  # ● 取消按键/事件处理
  #--------------------------------------------------------------------------
  def reset_handler(key)
    @handler.delete(key)
  end
  #--------------------------------------------------------------------------
  # ● 触发按键/事件处理
  #--------------------------------------------------------------------------
  def call_handler(key, *args)
    if @handler[key]
      @handler[key].call(*args)
      Input.update unless key.is_a?(Symbol)
    end
  end
  #--------------------------------------------------------------------------
  # ● 事件处理判定
  #--------------------------------------------------------------------------
  def handled?(key)
    @handler.has_key?(key)
  end
  #--------------------------------------------------------------------------
  # ● 更新光标输入
  #--------------------------------------------------------------------------
  def update_cursor
    update_up   (Input.trigger?(UP   )) if Input.repeat?(UP   )
    update_down (Input.trigger?(DOWN )) if Input.repeat?(DOWN )
    update_left (Input.trigger?(LEFT )) if Input.repeat?(LEFT )
    update_right(Input.trigger?(RIGHT)) if Input.repeat?(RIGHT)
    update_pageup   if Input.repeat?(L) and not handled?(L)
    update_pagedown if Input.repeat?(R) and not handled?(R)
  end
  #--------------------------------------------------------------------------
  # ● 设置按键输入
  #--------------------------------------------------------------------------
  def update_keypress
    update_cursor if cursor_respond?
    [A, B, C, X, Y, Z, L, R, F5, F6, F7, F8, F9, CTRL, ALT, SHIFT].each do |k|
      call_handler(k) if Input.trigger?(k)
    end
  end
end

#==============================================================================
# ■ Window_Selectable
#==============================================================================
class Window_Selectable
  include Window_Handler
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :item_max
  #--------------------------------------------------------------------------
  # ● 方法重定义
  #--------------------------------------------------------------------------
  unless method_defined?(:sailcat_windowcore_initialize)
    alias sailcat_windowcore_initialize initialize
    alias sailcat_windowcore_index= index=
    alias sailcat_windowcore_update_cursor_rect update_cursor_rect
  end
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     x      : 窗口的 X 坐标
  #     y      : 窗口的 Y 坐标
  #     width  : 窗口的宽
  #     height : 窗口的高
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    sailcat_windowcore_initialize(x, y, width, height)
    @handler = {}
  end
  #--------------------------------------------------------------------------
  # ● 设置光标的位置
  #     index : 新的光标位置
  #--------------------------------------------------------------------------
  def index=(index)
    need_call = (@index != index and self.active)
    self.sailcat_windowcore_index = index
    call_handler(:index_changed) if need_call
  end
  #--------------------------------------------------------------------------
  # ● 设置可见性
  #--------------------------------------------------------------------------
  def visible=(visible)
    need_call = self.visible != visible
    super
    call_handler(:visible_changed) if need_call
  end
  #--------------------------------------------------------------------------
  # ● 设置启用性
  #--------------------------------------------------------------------------
  def active=(active)
    call_handler(active ? :activated : :deactivated) if self.active != active
    super
    update_help if self.active and @help_window
  end
  #--------------------------------------------------------------------------
  # ● 获取开头行
  #--------------------------------------------------------------------------
  def top_row
    self.oy / item_height
  end
  #--------------------------------------------------------------------------
  # ● 设置开头行
  #     row : 显示开头的行
  #--------------------------------------------------------------------------
  def top_row=(row)
    # 窗口未开启时不调整
    return if self.openness < 255
    # row 未满 0 的场合更正为 0
    if row < 0
      row = 0
    end
    # row 超过 row_max - 1 的情况下更正为 row_max - 1
    if row > row_max - 1
      row = row_max - 1
    end
    self.oy = row * item_height
  end
  #--------------------------------------------------------------------------
  # ● 获取 1 页可以显示的行数
  #--------------------------------------------------------------------------
  def page_row_max
    (self.height - 32) / item_height
  end
  #--------------------------------------------------------------------------
  # ● 建立内容
  #--------------------------------------------------------------------------
  def create_contents
    contents.dispose if contents
    self.contents = Bitmap.new(width - 32, row_max * item_height)
  end
  #--------------------------------------------------------------------------
  # ● 获取光标间距
  #--------------------------------------------------------------------------
  def cursor_padding
    CURSOR_PADDING
  end
  #--------------------------------------------------------------------------
  # ● 获取列宽
  #--------------------------------------------------------------------------
  def column_width
    (self.width - cursor_padding * (@column_max - 1) - 32) / @column_max
  end
  #--------------------------------------------------------------------------
  # ● 获取数据项高
  #--------------------------------------------------------------------------
  def item_height
    line_height(1)
  end
  #--------------------------------------------------------------------------
  # ● 获取数据项矩形
  #--------------------------------------------------------------------------
  def item_rect(index)
    x = index % @column_max * (column_width + cursor_padding)
    y = index / @column_max * item_height
    Rect.new(x, y, column_width, item_height)
  end
  #--------------------------------------------------------------------------
  # ● 更新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    sailcat_windowcore_update_cursor_rect
    # 更新光标矩形
    self.cursor_rect = item_rect(@index).offset(0, -self.oy) if @index >= 0
  end
  #--------------------------------------------------------------------------
  # ● 光标有效判定
  #--------------------------------------------------------------------------
  def cursor_respond?
    @item_max > 0 and @index >= 0
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面
  #--------------------------------------------------------------------------
  def update
    super
    update_keypress if self.active
  end
  #--------------------------------------------------------------------------
  # ● 方向键处理
  #--------------------------------------------------------------------------
  def update_up(force);     update_index(8, force);                       end
  def update_down(force);   update_index(2, force);                       end
  def update_left(force);   update_index(4, force);                       end
  def update_right(force);  update_index(6, force);                       end
  #--------------------------------------------------------------------------
  # ● L键处理
  #--------------------------------------------------------------------------
  def update_pageup
    if Input.press?(CTRL)
      self.index = 0
    else
      scroll_page(top_row > 0 ? -1 : 0)
    end
  end
  #--------------------------------------------------------------------------
  # ● R键处理
  #--------------------------------------------------------------------------
  def update_pagedown
    if Input.press?(CTRL)
      self.index = @item_max - 1
    else
      scroll_page(top_row + page_row_max - 1 < row_max - 1 ? 1 : 0)
    end
  end
  #--------------------------------------------------------------------------
  # ● 更新移动位置
  #--------------------------------------------------------------------------
  def update_index(dir, force)
    step = dir == 2 ? @column_max : (dir == 8 ? -@column_max : dir - 5)
    columns = 2 - ((dir - 5).abs >> 1)
    if @column_max >= columns and (force or valid?(step))
      step += @item_max if step < 0
      $game_system.se_play($data_system.cursor_se)
      self.index = (@index + step) % @item_max
    end
  end
  #--------------------------------------------------------------------------
  # ● 有效移动判定
  #--------------------------------------------------------------------------
  def valid?(offset)
    @index + offset >= 0 and @index + offset < @item_max
  end
  #--------------------------------------------------------------------------
  # ● 翻页处理
  #--------------------------------------------------------------------------
  def scroll_page(value)
    return if value == 0
    $game_system.se_play($data_system.cursor_se)
    self.top_row += page_row_max * value
    self.index = (@index + page_item_max * value).limit(0, @item_max - 1)
  end
end

#==============================================================================
# ■ Window_Command
#==============================================================================
class Window_Command
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     width    : 窗口的宽
  #     commands : 命令字符串序列
  #--------------------------------------------------------------------------
  def initialize(width, commands)
    # 由命令的个数计算出窗口的高
    super(0, 0, width, window_h(commands.size))
    @item_max = commands.size
    @commands = commands
    create_contents
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #     color : 文字色
  #--------------------------------------------------------------------------
  def draw_item(index, color)
    change_color(color)
    rect = item_rect(index).inflate(-4, 0)
    contents.clear_rect(rect)
    draw_text(rect, @commands[index])
  end
end


#==============================================================================
# ■ Window_HorzCommand
#------------------------------------------------------------------------------
#  水平排列的命令窗口。
#==============================================================================
class Window_HorzCommand < Window_Selectable
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize(width, commands)
    super(0, 0, width, window_h)
    @item_max = @column_max = commands.size
    @commands = commands
    create_contents
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    for i in 0...@item_max
      draw_item(i, system_color)
    end
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #     color : 文字色
  #--------------------------------------------------------------------------
  def draw_item(index, color)
    change_color(color)
    rect = item_rect(index)
    contents.clear_rect(rect)
    draw_text(rect, @commands[index], 1)
  end
  #--------------------------------------------------------------------------
  # ● 项目无效化
  #     index : 项目编号
  #--------------------------------------------------------------------------
  def disable_item(index)
    draw_item(index, disabled_color)
  end
  #--------------------------------------------------------------------------
  # ● 获取光标间距
  #--------------------------------------------------------------------------
  def cursor_padding
    CURSOR_PADDING_HORZCOMMAND
  end
end

#==============================================================================
# ■ Window_MenuStatus
#==============================================================================
class Window_MenuStatus
  #--------------------------------------------------------------------------
  # ● 初始化目标
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, -160, 0)
    refresh
    deactivate
    self.index = -1
  end
  #--------------------------------------------------------------------------
  # ● 获取数据项高
  #--------------------------------------------------------------------------
  def item_height
    [(self.height - 32) / [@item_max, 4].max, line_height(3)].max
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    @item_max = $game_party.actors.size
    create_contents
    draw_actors
  end
  #--------------------------------------------------------------------------
  # ● 绘制角色
  #--------------------------------------------------------------------------
  def draw_actors
    x = 64
    data_width = column_width - x - 36
    col1 = [204, data_width >> 1].max
    col2 = data_width - col1
    for i in 0...$game_party.actors.size
      y = i * item_height
      actor = $game_party.actors
      draw_actor_graphic(actor, x - 40, y + item_height * 5 / 6)
      draw_actor_name(actor, x, y)
      draw_actor_class(actor, x + 144, y, data_width - 112)
      draw_actor_level(actor, x, y + item_height / 3)
      draw_actor_state(actor, x + 90, y + item_height / 3, col1 - 90)
      draw_actor_exp(actor, x, y + item_height * 2 / 3, col1)
      draw_actor_hp(actor, x + col1 + 32, y + item_height / 3, col2)
      draw_actor_sp(actor, x + col1 + 32, y + item_height * 2 / 3, col2)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    super
  end
end

#==============================================================================
# ■ Window_Data
#------------------------------------------------------------------------------
#  显示物品、特技、武器、防具的列表窗口。
#==============================================================================
class Window_Data < Window_Selectable
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height, back_opacity = nil, column_max = 2)
    super(x, y, width, height)
    self.back_opacity = back_opacity || BACK_OPACITY_DEFAULT
    @column_max = column_max
    refresh
    self.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 获取物品
  #--------------------------------------------------------------------------
  def item
    return @data[self.index]
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    make_data
    @item_max = @data.size
    if @item_max > 0
      create_contents
      @drawn = [false] * @item_max
      draw_page(top_row * @column_max)
    else
      contents.dispose if contents
      self.contents = nil
    end
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    @data = []
  end
  #--------------------------------------------------------------------------
  # ● 绘制指定页
  #--------------------------------------------------------------------------
  def draw_page(index)
    return if @item_max == 0
    for i in index...index + page_item_max
      draw_item(i) if i < @item_max and not @drawn
    end
  end
  #--------------------------------------------------------------------------
  # ● 翻页更新绘制
  #--------------------------------------------------------------------------
  def top_row=(row)
    super
    draw_page(row * @column_max) if self.openness == 255
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    @drawn[index] = true
    case item
    when RPG::Skill
      number = item.sp_cost
    when RPG::Item, RPG::Weapon, RPG::Armor
      number = $game_party.any_number(item)
    else
      return
    end
    enabled = (@enable_proc == nil or @enable_proc.call(item))
    rect = item_rect(index).inflate(-4, 0)
    contents.clear_rect(rect)
    if item.is_a?(RPG::Skill)
      draw_item_name(item, rect.x, rect.y, enabled, rect.width - 48)
      change_color(enabled ? sp_cost_color : disabled_color)
      draw_text(rect.right - 48, rect.y, 48, item_height, number, 2)
    else
      number_width = text_size(ITEM_MAX).width.limit(24, 66) + 16
      draw_item_name(item, rect.x, rect.y, enabled, rect.width - number_width)
      draw_text(rect.right - number_width, rect.y, 16, item_height, ":", 1)
      draw_text(rect.right - number_width + 16, rect.y,
        number_width - 16, item_height, number, 2)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新帮助文本
  #--------------------------------------------------------------------------
  def update_help
    @help_window.set_text(self.item == nil ? "" : self.item.description)
  end
end

#==============================================================================
# ■ Window_Item
#==============================================================================
class Window_Item < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    if $game_temp.in_battle
      super(0, window_h, 0, -window_h - window_h(4), BACK_OPACITY_IN_BATTLE)
    else
      super(0, window_h, 0, -window_h)
    end
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    @data = $game_party.send($game_temp.in_battle ? :sorted_items : :all_items)
    @enable_proc = Proc.new {|item|
      item.is_a?(RPG::Item) and $game_party.item_can_use?(item.id)}
  end
end

#==============================================================================
# ■ Window_Skill
#==============================================================================
class Window_Skill < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize(actor)
    @actor = actor
    if $game_temp.in_battle
      super(0, window_h, 0, -window_h - window_h(4), BACK_OPACITY_IN_BATTLE)
    else
      super(0, window_h << 1, 0, -window_h << 1)
    end
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    @data.concat(@actor.learned_skills)
    @enable_proc = Proc.new {|skill| @actor.skill_can_use?(skill.id)}
  end
  #--------------------------------------------------------------------------
  # ● 获取选中的特技
  #--------------------------------------------------------------------------
  def skill
    item
  end
end

#==============================================================================
# ■ Window_Target
#==============================================================================
class Window_Target
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, (SCREEN_W + CURSOR_PADDING) >> 1, 0)
    self.back_opacity = 255
    self.z += 10
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 获取数据项高
  #--------------------------------------------------------------------------
  def item_height
    [(self.height - 32) / [@item_max, 4].max, line_height(3)].max
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    @item_max = $game_party.actors.size
    create_contents
    draw_actors
  end
  #--------------------------------------------------------------------------
  # ● 绘制角色
  #--------------------------------------------------------------------------
  def draw_actors
    col = (column_width - 16) >> 1
    for i in 0...$game_party.actors.size
      x = 4
      y = i * item_height
      actor = $game_party.actors
      draw_actor_name(actor, x, y, col)
      draw_actor_class(actor, x + col, y, col + 8)
      draw_actor_level(actor, x + 8, y + item_height / 3)
      draw_actor_state(actor, x + 8, y + item_height * 2 / 3, col)
      draw_actor_hp(actor, x + 8 + col, y + item_height / 3, col)
      draw_actor_sp(actor, x + 8 + col, y + item_height * 2 / 3, col)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    if @index <= -2
      y = (@index + TARGET_SELF_OFFSET_DEFAULT) * item_height
      if @index < self.top_row
        self.top_row = @index
      elsif @index > self.top_row + (self.page_row_max - 1)
        self.top_row = @index - (self.page_row_max - 1)
      end
      cursor_rect.set(0, y - self.oy, column_width, line_height)
    elsif @index == -1
      cursor_rect.set(0, 0, contents.width, contents.height)
    else
      super
    end
  end
end

#==============================================================================
# ■ Window_EquipRight
#==============================================================================
class Window_EquipRight < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor : 角色
  #--------------------------------------------------------------------------
  def initialize(actor)
    @actor = actor
    width = [368, SCREEN_W >> 1].max
    super(SCREEN_W - width, window_h, width, window_h(5), nil, 1)
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    @data.concat(@actor.all_equipment)
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    word = Vocab.send([:weapon, :armor1, :armor2, :armor3, :armor4][index])
    change_color(system_color)
    draw_text(4, item_height * index, 92, item_height, word)
    draw_item_name(item, 92, item_height * index,
      !@actor.equip_fix?(index), column_width - 100)
  end
end

#==============================================================================
# ■ Window_EquipItem
#==============================================================================
class Window_EquipItem < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor      : 角色
  #     equip_type : 装备部位 (0~3)
  #--------------------------------------------------------------------------
  def initialize(actor, equip_type)
    @actor = actor
    @equip_type = equip_type
    super(0, window_h + window_h(5), 0, -window_h - window_h(5))
    self.active = false
    self.index = -1
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    # 添加可以装备的武器
    if @equip_type == 0
      weapon_set = $data_classes[@actor.class_id].weapon_set
      @data.push($game_party.sorted_weapons.select do |weapon|
        weapon_set.include?(weapon.id)
      end)
    end
    # 添加可以装备的防具
    if @equip_type != 0
      armor_set = $data_classes[@actor.class_id].armor_set
      @data.push($game_party.sorted_armors.select do |armor|
        armor_set.include?(armor.id) and armor.kind == @equip_type - 1
      end)
    end
    # 添加空白
    @data.push(nil)
  end
end

#==============================================================================
# ■ Window_ShopCommand
#==============================================================================
class Window_ShopCommand < Window_HorzCommand
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(SCREEN_W - 160, [Vocab.buy, Vocab.sell, Vocab.cancel])
    moveto(0, window_h)
  end
end

#==============================================================================
# ■ Window_ShopBuy
#==============================================================================
class Window_ShopBuy < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     shop_goods : 商品
  #--------------------------------------------------------------------------
  def initialize(shop_goods)
    @shop_goods = shop_goods
    width = [368, SCREEN_W >> 1].max
    super(0, window_h << 1, width, -window_h << 1, nil, 1)
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    sets = [$data_items, $data_weapons, $data_armors]
    @data.concat(@shop_goods.map {|i| sets[i[0]][i[1]]}).compact!
    @enable_proc = Proc.new {|item| item.price <= $game_party.gold and
      (!ITEM_MAX or $game_party.any_number(item) < ITEM_MAX)}
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目编号
  #--------------------------------------------------------------------------
  def draw_item(index)
    item = @data[index]
    number = item.price
    enabled = @enable_proc.call(item)
    rect = item_rect(index).inflate(-4, 0)
    contents.clear_rect(rect)
    draw_item_name(item, rect.x, rect.y, enabled, rect.width - 88)
    draw_text(rect.right - 88, rect.y, 88, item_height, number.to_s, 2)
  end
end

#==============================================================================
# ■ Window_ShopSell
#==============================================================================
class Window_ShopSell < Window_Data
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, window_h << 1, 0, -window_h << 1)
  end
  #--------------------------------------------------------------------------
  # ● 生成数据
  #--------------------------------------------------------------------------
  def make_data
    super
    @data.concat($game_party.all_items)
    @enable_proc = Proc.new {|item| item.price > 0}
  end
end

#==============================================================================
# ■ Window_Message
#==============================================================================
class Window_Message
  #--------------------------------------------------------------------------
  # ● 初始化状态
  #--------------------------------------------------------------------------
  def initialize
    super(80, SCREEN_H - window_h(4) - 16, SCREEN_W - 160, window_h(4))
    create_contents
    hide
    self.z = 9998
    @fade_in = false
    @fade_out = false
    @contents_showing = false
    @cursor_width = 0
    deactivate
    self.index = -1
  end
  #--------------------------------------------------------------------------
  # ● 建立内容
  #--------------------------------------------------------------------------
  def create_contents
    contents.dispose if contents
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    x = $game_temp.choice_start == 0 ? 8 : 0
    y = 0
    @cursor_width = 0
    @lines = 0
    # 有等待显示的文字的情况下
    if $game_temp.message_text != nil
      draw_text_ex(4 + x, y, $game_temp.message_text)
    end
    # 选择项的情况
    if $game_temp.choice_max > 0
      @item_max = $game_temp.choice_max
      activate
      self.index = 0
    end
    # 输入数值的情况
    make_input_number_window if $game_temp.num_input_variable_id > 0
  end
  #--------------------------------------------------------------------------
  # ● 折行处理
  #--------------------------------------------------------------------------
  def process_new_line(text, pos)
    @lines += 1
    # 刷新选择项及光标的高
    if @lines == $game_temp.choice_start
      pos[2] += 8
    elsif @lines > $game_temp.choice_start
      @cursor_width = [@cursor_width, pos[0]].max - 4
    end
    super
  end
  #--------------------------------------------------------------------------
  # ● 处理控制字符
  #     code : 控制命令符
  #--------------------------------------------------------------------------
  def process_escape_character(code, text, pos)
    super
    case code.upcase
    when 'G'
      make_gold_window
    end
  end
  #--------------------------------------------------------------------------
  # ● 生成金钱窗口
  #--------------------------------------------------------------------------
  def make_gold_window
    return if @gold_window
    @gold_window = Window_Gold.new
    @gold_window.x = SCREEN_W - 80 - @gold_window.width
    if $game_temp.in_battle
      @gold_window.y = (SCREEN_H >> 1) - @gold_window.height + 16
    else
      @gold_window.y = self.y >= 128 ? 32 : SCREEN_H - @gold_window.height - 32
    end
    @gold_window.opacity = self.opacity
    @gold_window.back_opacity = self.back_opacity
  end
  #--------------------------------------------------------------------------
  # ● 生成数值输入窗口
  #--------------------------------------------------------------------------
  def make_input_number_window
    digits_max = $game_temp.num_input_digits_max
    number = $game_variables[$game_temp.num_input_variable_id]
    @input_number_window = Window_InputNumber.new(digits_max)
    @input_number_window.number = number
    @input_number_window.x = self.x - 8
    @input_number_window.y = self.y + line_height($game_temp.num_input_start)
  end
  #--------------------------------------------------------------------------
  # ● 设置窗口位置与不透明度
  #--------------------------------------------------------------------------
  def reset_window
    if $game_temp.in_battle
      self.y = 16
    else
      case $game_system.message_position
      when 0  # 上
        self.y = 16
      when 1  # 中
        self.y = (SCREEN_H - self.height) >> 1
      when 2  # 下
        self.y = SCREEN_H - self.height - 16
      end
    end
    self.opacity = $game_system.message_frame == 0 ? 255 : 0
    self.back_opacity = 160
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    if @index >= 0
      n = $game_temp.choice_start + @index
      self.cursor_rect.set(8, line_height(n), @cursor_width, line_height)
    else
      self.cursor_rect.empty
    end
  end
end

#==============================================================================
# ■ Window_PartyCommand
#==============================================================================
class Window_PartyCommand < Window_HorzCommand
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(SCREEN_W, [Vocab.fight, Vocab.escape])
    self.back_opacity = BACK_OPACITY_IN_BATTLE
    @column_max = 4
    contents.clear
    draw_item(0, normal_color)
    draw_item(1, $game_temp.battle_can_escape ? normal_color : disabled_color)
    update_cursor_rect
    deactivate
    hide
  end
  #--------------------------------------------------------------------------
  # ● 描绘项目
  #     index : 项目标号
  #     color : 文字颜色
  #--------------------------------------------------------------------------
  def draw_item(index, color)
    change_color(color)
    rect = item_rect(index + 1).inflate(-4, 0)
    contents.clear_rect(rect)
    draw_text(rect, @commands[index], 1)
  end
  #--------------------------------------------------------------------------
  # ● 更新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    self.cursor_rect = item_rect(@index + 1)
  end
end

#==============================================================================
# ■ Window_DebugLeft
#==============================================================================
class Window_DebugLeft
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 192, 0)
    @step = (SCREEN_H - window_h(3) - 32) / item_height
    @switch_max = ($data_system.switches.size + @step - 2) / @step
    @variable_max = ($data_system.variables.size + @step - 2) / @step
    @item_max = @switch_max + @variable_max
    create_contents
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    @switch_max.times do |i|
      text = sprintf("S [%04d-%04d]", i * @step + 1, (i + 1) * @step)
      draw_text(item_rect(i).inflate(-4, 0), text)
    end
    @variable_max.times do |i|
      text = sprintf("V [%04d-%04d]", i * @step + 1, (i + 1) * @step)
      draw_text(item_rect(i + @switch_max).inflate(-4, 0), text)
    end
  end
  #--------------------------------------------------------------------------
  # ● 获取开头显示的 ID
  #--------------------------------------------------------------------------
  def top_id
    if self.index < @switch_max
      self.index * @step + 1
    else
      (self.index - @switch_max) * @step + 1
    end
  end
end

#==============================================================================
# ■ Window_DebugRight
#==============================================================================
class Window_DebugRight
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :mode                     # 模式 (0:开关、1:变量)
  attr_reader   :top_id                   # 开头显示的 ID
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(192, 0, -192, -window_h(3))
    deactivate
    @mode = 0
    @top_id = 1
    @item_max = page_row_max
    create_contents
    refresh
    self.index = -1
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    for i in 0..page_row_max
      if @mode == 0
        name = $data_system.switches[@top_id + i].to_s
        status = $game_switches[@top_id + i] ? "[ON]" : "[OFF]"
      else
        name = $data_system.variables[@top_id + i].to_s
        status = $game_variables[@top_id + i].to_s
      end
      id_text = sprintf("%04d:", @top_id + i)
      width = text_size(id_text).width
      rect = item_rect(i).inflate(-4, 0)
      x = rect.x
      y = rect.y
      draw_text(x, y, width, item_height, id_text)
      draw_text(x + width, y, rect.right - width - 100, item_height, name)
      draw_text(rect.right - 100, y, 100, item_height, status, 2)
    end
  end
  #--------------------------------------------------------------------------
  # ● 左键处理
  #--------------------------------------------------------------------------
  def update_left(force)
    $scene.set_variable(@top_id + @index, -1) if @mode == 1
  end
  #--------------------------------------------------------------------------
  # ● 右键处理
  #--------------------------------------------------------------------------
  def update_right(force)
    $scene.set_variable(@top_id + @index, +1) if @mode == 1
  end
  #--------------------------------------------------------------------------
  # ● L键处理
  #--------------------------------------------------------------------------
  def update_pageup
    $scene.set_variable(@top_id + @index, +10) if @mode == 1
  end
  #--------------------------------------------------------------------------
  # ● R键处理
  #--------------------------------------------------------------------------
  def update_pagedown
    $scene.set_variable(@top_id + @index, -10) if @mode == 1
  end
end

#==============================================================================
# ■ Window_Help
#==============================================================================
class Window_Help
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 0, window_h)
    create_contents
  end
  #--------------------------------------------------------------------------
  # ● 设置文本
  #     text  : 窗口显示的字符串
  #     align : 对齐方式 (0..左对齐、1..中间对齐、2..右对齐)
  #--------------------------------------------------------------------------
  def set_text(text, align = 0)
    # 如果文本和对齐方式的至少一方与上次的不同
    if text != @text or align != @align
      # 再描绘文本
      contents.clear
      reset_font_settings
      if text.escaped?
        if align == 0
          draw_text_ex(4, 0, text)
        else
          width = calc_text_width(convert_escape_characters(text))
          if align == 1
            draw_text_ex((contents.width - width) >> 1, 0, text)
          else
            draw_text_ex((contents.width - width - 4), 0, text)
          end
        end
      else
        draw_text(4, 0, contents.width - 8, line_height, text, align)
      end
      @text = text
      @align = align
      @actor = nil
    end
    self.visible = true
  end
  #--------------------------------------------------------------------------
  # ● 设置敌人
  #     enemy : 要显示名字和状态的敌人
  #--------------------------------------------------------------------------
  def set_enemy(enemy)
    text = enemy.name
    state_width = contents.width - text_size(text + "  ").width
    state_text = make_battler_state_text(enemy, state_width, false)
    if state_text != ""
      text += "  " + state_text
    end
    set_text(text, 1)
  end
end

#==============================================================================
# ■ Window_Gold
#==============================================================================
class Window_Gold
  #--------------------------------------------------------------------------
  # ● 初始化窗口
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 160, window_h)
    create_contents
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    draw_currency_value($game_party.gold, Vocab.gold, 4, 0, 120)
  end
end

#==============================================================================
# ■ Window_PlayTime
#==============================================================================
class Window_PlayTime
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 160, window_h(2))
    create_contents
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    return unless open?
    contents.clear
    change_color(system_color)
    draw_text(4, 0, 120, line_height, Vocab.playtime)
    @total_sec = Graphics.frame_count / Graphics.frame_rate
    hour = @total_sec / 60 / 60
    min = @total_sec / 60 % 60
    sec = @total_sec % 60
    text = sprintf("%02d:%02d:%02d", hour, min, sec)
    change_color(normal_color)
    draw_text(4, line_height, 120, line_height, text, 2)
  end
end

#==============================================================================
# ■ Window_Steps
#==============================================================================
class Window_Steps
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, 0, 160, window_h(2))
    create_contents
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    change_color(system_color)
    draw_text(4, 0, 120, line_height, Vocab.steps)
    change_color(normal_color)
    draw_text(4, line_height, 120, line_height, $game_party.steps, 2)
  end
end

#==============================================================================
# ■ Window_SkillStatus
#==============================================================================
class Window_SkillStatus
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor : 角色
  #--------------------------------------------------------------------------
  def initialize(actor)
    super(0, window_h, 0, window_h)
    create_contents
    @actor = actor
    refresh
  end
end

#==============================================================================
# ■ Window_EquipLeft
#==============================================================================
class Window_EquipLeft < Window_Base
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor : 角色
  #--------------------------------------------------------------------------
  def initialize(actor)
    width = [368, SCREEN_W >> 1].max
    super(0, window_h, -width, window_h(5))
    create_contents
    @actor = actor
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    draw_actor_name(@actor, 4, 0)
    draw_actor_level(@actor, 4, line_height)
    draw_actor_parameter(@actor, 4, line_height(2), 0)
    draw_actor_parameter(@actor, 4, line_height(3), 1)
    draw_actor_parameter(@actor, 4, line_height(4), 2)
    [:atk, :pdef, :mdef].each_with_index do |sym, i|
      value = instance_variable_get("@new_#{sym}")
      next if value == nil
      change_color(system_color)
      draw_text(160, line_height(i + 2), 40, line_height, "→", 1)
      change_color(param_change_color(value - @actor.send(sym)))
      draw_text(200, line_height(i + 2), 36, line_height, value, 2)
    end
  end
end

#==============================================================================
# ■ Window_Status
#==============================================================================
class Window_Status
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor : 角色
  #--------------------------------------------------------------------------
  def initialize(actor)
    super(0, 0, 0, 0)
    create_contents
    @actor = actor
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    half = SCREEN_W >> 1
    draw_actor_graphic(@actor, 40, 112)
    draw_actor_name(@actor, 4, 0)
    draw_actor_class(@actor, 148, 0)
    draw_actor_level(@actor, 96, line_height)
    draw_actor_state(@actor, 96, line_height(2))
    draw_actor_hp(@actor, 96, line_height(3.5), 172)
    draw_actor_sp(@actor, 96, line_height(4.5), 172)
    for i in 0..6
      draw_actor_parameter(@actor, 96, line_height(i + (i>2 ? 6.5 : 6)), i)
    end
    change_color(system_color)
    draw_text(half, line_height(1.5), 80, line_height, Vocab.exp)
    draw_text(half, line_height(2.5), 80, line_height, Vocab.next_level)
    change_color(normal_color)
    draw_text(half + 80, line_height(1.5), 84, line_height, @actor.exp_s, 2)
    draw_text(half + 80, line_height(2.5), 84, line_height,
      @actor.next_rest_exp_s, 2)
    change_color(system_color)
    draw_text(half, line_height(5), 96, line_height, Vocab.equip)
    draw_item_name(@actor.weapon, half + 16, line_height(6.5))
    @actor.all_armors.each_with_index do |armor, i|
      draw_item_name(armor, half + 16, line_height(8 + i * 1.5))
    end
  end
end

#==============================================================================
# ■ Window_SaveFile
#==============================================================================
class Window_SaveFile
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     file_index : 存档文件的索引 (0~3)
  #     filename   : 文件名
  #--------------------------------------------------------------------------
  def initialize(file_index, filename)
    height = (SCREEN_H - window_h) >> 2
    super(0, window_h + (file_index & 3) * height, 0, height)
    create_contents
    @file_index = file_index
    read_save_file
    refresh
    @selected = false
  end
  #--------------------------------------------------------------------------
  # ● 读取存档
  #--------------------------------------------------------------------------
  def read_save_file
    @filename = "Save#{@file_index + 1}.rxdata"
    @time_stamp = Time.at(0)
    @file_exist = FileTest.exist?(@filename)
    if @file_exist
      file = File.open(@filename, "r")
      @time_stamp = file.mtime
      @characters = Marshal.load(file)
      @frame_count = Marshal.load(file)
      @game_system = Marshal.load(file)
      @game_switches = Marshal.load(file)
      @game_variables = Marshal.load(file)
      @total_sec = @frame_count / Graphics.frame_rate
      file.close
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    # 描绘文件编号
    change_color(normal_color)
    name = "#{Vocab.file} #{@file_index + 1}"
    draw_text(4, 0, SCREEN_W - 40, line_height, name)
    @name_width = contents.text_size(name).width
    # 存档文件存在的情况下
    if @file_exist
      # 描绘角色
      for i in 0...@characters.size
        bitmap = RPG::Cache.character(@characters[0], @characters[1])
        cw = bitmap.rect.width >> 2
        ch = bitmap.rect.height >> 2
        src_rect = Rect.new(0, 0, cw, ch)
        x = 300 - (@characters.size << 5) + (i << 6) - (cw >> 1)
        contents.blt(x, 68 - ch, bitmap, src_rect)
      end
      # 描绘游戏时间
      hour = @total_sec / 60 / 60
      min = @total_sec / 60 % 60
      sec = @total_sec % 60
      time_string = sprintf("%02d:%02d:%02d", hour, min, sec)
      draw_text(4, 8, SCREEN_W - 40, line_height, time_string, 2)
      # 描绘时间标记
      time_string = @time_stamp.strftime("%Y/%m/%d %H:%M")
      draw_text(4, 40, SCREEN_W - 40, line_height, time_string, 2)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    if @selected
      cursor_rect.set(0, 0, @name_width + 8, line_height)
    else
      cursor_rect.empty
    end
  end
end

#==============================================================================
# ■ Window_Numeric
#------------------------------------------------------------------------------
#  处理数值输入的窗口。
#==============================================================================
class Window_Numeric < Window_Base
  include Window_Handler
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader   :number                   # 当前数字值
  attr_reader   :magnitude                # 输入数字的进制
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super(x, y, width, height)
    create_contents
    @handler = {}
    @min = 0
    @max = 0
    @magnitude = 10
    @number = 0
    @index = 0
    @digits_max = 0
  end
  #--------------------------------------------------------------------------
  # ● 是否按位数分开输入
  #--------------------------------------------------------------------------
  def digit_split
    @min >= 0 and @digits_max > 0
  end
  #--------------------------------------------------------------------------
  # ● 最大位数
  #--------------------------------------------------------------------------
  def digits_max
    return @digits_max if digit_split
    return contents.width / (contents.font.size >> 1) if !@max
    @max.to_s(@magnitude).size + (@min < 0 ? 1 : 0)
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面
  #--------------------------------------------------------------------------
  def update
    super
    update_keypress if self.active
  end
  #--------------------------------------------------------------------------
  # ● 设置数字值
  #     number : 新值
  #--------------------------------------------------------------------------
  def number=(number)
    @number = number.limit(@min, @max)
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 数字的字串
  #--------------------------------------------------------------------------
  def number_s
    value = @number.to_s(@magnitude)
    value = "0" + value while value.size < @digits_max
    return value
  end
  #--------------------------------------------------------------------------
  # ● 设置进制
  #     magnitude : 新进制
  #--------------------------------------------------------------------------
  def magnitude=(magnitude)
    @magnitude = magnitude.limit(2, 36)
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 光标有效判定
  #--------------------------------------------------------------------------
  def cursor_respond?
    @min != @max or (@min.nil? and @max.nil?)
  end
  #--------------------------------------------------------------------------
  # ● 描绘数字
  #--------------------------------------------------------------------------
  def draw_number(x, y, width = nil)
    change_color(normal_color)
    if digit_split
      width ||= (contents.font.size >> 1) + 8
      number_s.scan(/./).each_with_index do |char, i|
        draw_text(x + i * width, y, width, line_height, char, 1)
      end
      @cursor_width = width
      @rect = Rect.new(x, y, @cursor_width * @digits_max, line_height)
    else
      max_width = contents.font.size * digits_max >> 1
      width ||= max_width
      ox = width - max_width
      draw_text(x, y, width, line_height, number_s, 2)
      @rect = Rect.new(x + ox, y, max_width, line_height).inflate(4, 0)
    end
  end
  #--------------------------------------------------------------------------
  # ● 更新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    if digit_split
      width = @cursor_width
      cursor_rect.set(@rect.x + @index * width , @rect.y, width, @rect.height)
    else
      self.cursor_rect = @rect
    end
  end
  #--------------------------------------------------------------------------
  # ● 更新光标矩形
  #--------------------------------------------------------------------------
  def move_index(index)
    @index = (index + digits_max) % digits_max
    # 演奏光标 SE
    $game_system.se_play($data_system.cursor_se)
    update_cursor_rect
  end
  #--------------------------------------------------------------------------
  # ● 光标键处理
  #--------------------------------------------------------------------------
  def update_up(force);     update_value(+2);                             end
  def update_down(force);   update_value(-2);                             end
  def update_left(force);   update_value(-1);                             end
  def update_right(force);  update_value(+1);                             end
  def update_pageup;        update_value(-3);                             end
  def update_pagedown;      update_value(+3);                             end
  #--------------------------------------------------------------------------
  # ● 更新输入数值
  #--------------------------------------------------------------------------
  def update_value(value)
    # 记忆原来的数值
    last_number = number = @number
    # 更新位是99的情况下
    if value.abs == 99
      # 直接设为最大/最小值
      number = value == 99 ? @max.to_i : @min.to_i
    # 更新位是0的情况下
    elsif value == 0
      # 清零
      number = 0.limit(@min, @max)
    # 更新位是其他的情况下
    else
      # 如果是分位输入
      if digit_split
        case value
        # 按下左右键的情况下
        when 1, -1
          return move_index(@index + value)
        # 按下上下键的情况下
        when 2, -2
          change = Integer(@magnitude ** (digits_max - @index - 1))
          place = (number / change) % @magnitude
          number -= place * change
          number += (place + (value >> 1) + @magnitude) % @magnitude * change
          number = number.limit(@min, @max)
        # 按下L/R键的情况下
        when 3, -3
          return move_index(value == 3 ? digits_max - 1 : 0)
        end
      # 如果不是分位输入
      else
        # 增减变化值
        key = 0
        key += 3 if Input.press?(NUM_KI)
        key += 6 if Input.press?(NUM_MI)
        key += 9 if Input.press?(NUM_BI)
        change = (value <=> 0) * Integer(@magnitude ** (value.abs + key - 1))
        number = (number + change).limit(@min, @max)
      end
    end
    # 数值无变化的情况下
    if number == last_number
      # 演奏冻结 SE
      $game_system.se_play($data_system.buzzer_se)
    else
      # 演奏光标 SE
      $game_system.se_play($data_system.cursor_se)
      self.number = number
    end
  end
end

#==============================================================================
# ■ Window_ShopNumber
#==============================================================================
class Window_ShopNumber < Window_Numeric
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    width = [368, SCREEN_W >> 1].max
    super(0, window_h << 1, width, -window_h << 1)
    @item = nil
    @min = 1
    @max = 1
    @price = 0
    @number = 1
  end
  #--------------------------------------------------------------------------
  # ● 设置物品、最大个数、价格
  #--------------------------------------------------------------------------
  def set(item, max, price)
    @item = item
    @max = max
    @price = price
    @number = 1
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    # 计算需要显示多少行文字
    row_max = (width - 32) / line_height
    row = (row_max - (SHOW_SHOP_HINT ? 6 : 3)) >> 1
    # 清除描画区域
    contents.clear_rect(0, 0, width - 32, line_height(row + 3))
    # 描绘物品和数量
    draw_item_name(@item, 4, line_height(row), width - 128)
    change_color(normal_color)
    draw_text(width - 124, line_height(row), 32, line_height, "×")
    # 数量超过6位数的情况下在下一行描绘
    if @max.nil? or digits_max > 6
      draw_number(4, line_height(row + 1), width - 40)
    else
      draw_number(4, line_height(row), width - 40)
    end
    update_cursor_rect
    # 描绘合计价格和货币单位
    total = @price * @number
    draw_currency_value(total, Vocab.gold, 4, line_height(row + 2), width - 40)
    # 描绘提示
    if SHOW_SHOP_HINT and @hint_text != make_hint_text
      contents.clear_rect(0, line_height(row + 3), width - 32, line_height(4))
      draw_text_ex(4, line_height(row + 3), @hint_text = make_hint_text)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def make_hint_text
    str = Vocab.num_hints[10..(@max ? -1 : -2)].join
    max = Vocab.num_hints[0...[digits_max, 10].min]
    max[9] = sprintf(max[9], Input.key_name(NUM_BI)) if max.size == 10
    max[6] = sprintf(max[6], Input.key_name(NUM_MI)) if max.size >= 7
    max[3] = sprintf(max[3], Input.key_name(NUM_KI)) if max.size >= 4
    str += max.join
  end
end

#==============================================================================
# ■ Window_ShopStatus
#==============================================================================
class Window_ShopStatus
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    x = [368, SCREEN_W >> 1].max
    super(x, window_h << 1, -x, -window_h << 1)
    create_contents
    @item = nil
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    return if @item == nil
    number = $game_party.any_number(@item)
    draw_key_value_pair(4, 0, Vocab.hold_number, number, number, width - 40)
    return if @item.is_a?(RPG::Item)
    # 添加装备品信息
    for i in 0...$game_party.actors.size
      # 获取角色
      actor = $game_party.actors
      # 可以装备为普通文字颜色、不能装备设置为无效文字颜色
      change_color(actor.equippable?(@item) ? normal_color : disabled_color)
      # 描绘角色名字
      draw_actor_name(actor, 4, line_height(i * 2 + 2))
      # 可以装备的情况
      if actor.equippable?(@item)
        item1 = mirror_item(actor)
        # 武器的情况
        if @item.is_a?(RPG::Weapon)
          atk1 = item1 != nil ? item1.atk : 0
          atk2 = @item != nil ? @item.atk : 0
          change = atk2 - atk1
        end
        # 防具的情况
        if @item.is_a?(RPG::Armor)
          pdef1 = item1 != nil ? item1.pdef : 0
          mdef1 = item1 != nil ? item1.mdef : 0
          pdef2 = @item != nil ? @item.pdef : 0
          mdef2 = @item != nil ? @item.mdef : 0
          change = pdef2 - pdef1 + mdef2 - mdef1
        end
        # 描绘能力值变化
        draw_text(124, line_height(i * 2 + 2), 112, line_height,
          sprintf("%+d", change), 2)
      end
      # 描绘物品
      if item1 != nil
        draw_item_name(item1, 4, line_height(i * 2 + 3),
          actor.equippable?(@item))
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 获取与当前售卖品对应的角色装备
  #     actor : 角色
  #--------------------------------------------------------------------------
  def mirror_item(actor)
    # 获取与当前售卖品对应的装备品
    if @item.is_a?(RPG::Weapon)
      item1 = actor.weapon
    else
      item1 = actor.all_armors[@item.kind]
    end
  end
end

#==============================================================================
# ■ Window_NameEdit
#==============================================================================
class Window_NameEdit
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     actor    : 角色
  #     max_char : 最大字数
  #--------------------------------------------------------------------------
  def initialize(actor, max_char)
    super(0, 0, 0, window_h(3))
    create_contents
    @actor = actor
    @name = actor.name
    @max_char = max_char
    # 控制名字在最大字数以内
    name_array = @name.split(//)[0...@max_char]
    @name = name_array.join
    @default_name = @name
    @index = name_array.size
    refresh
    update_cursor_rect
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    # 描绘名称
    name_array = @name.split(//)
    half = SCREEN_W >> 1
    for i in 0...@max_char
      c = name_array
      if c == nil
        c = "_"
      end
      x = half - @max_char * 14 + i * 28
      draw_text(x, line_height, 28, line_height, c, 1)
    end
    # 描绘图形
    draw_actor_graphic(@actor, half - @max_char * 14 - 40, line_height(2.5))
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    x = (SCREEN_W >> 1) - @max_char * 14 + @index * 28
    cursor_rect.set(x, line_height, 28, line_height)
  end
end

#==============================================================================
# ■ Window_NameInput
#==============================================================================
class Window_NameInput
  include Window_Handler
  #--------------------------------------------------------------------------
  # ● 常量
  #--------------------------------------------------------------------------
  CHARACTER_TABLE_NORMAL =
  [
    "Esc","1","2","3","4","5","6","7","8","9","0","-","=","<-Bksp",
    "`","q","w","e","r","t","y","u","i","o","p","[","]","\\",
    "CAPS","a","s","d","f","g","h","j","k","l",";","'","Enter",
    "Shift","z","x","c","v","b","n","m",",",".","/","Shift", " "
  ]
  CHARACTER_TABLE_CAPS =
  [
    "Esc","1","2","3","4","5","6","7","8","9","0","-","=","<-Bksp",
    "`","Q","W","E","R","T","Y","U","I","O","P","[","]","\\",
    "caps","A","S","D","F","G","H","J","K","L",";","'","Enter",
    "Shift","Z","X","C","V","B","N","M",",",".","/","Shift", " "
  ]
  CHARACTER_TABLE_SHIFT =
  [
    "Esc","!","@","#","$","%","^","&","*","(",")","_","+","<-Bksp",
    "~","Q","W","E","R","T","Y","U","I","O","P","{","}","|",
    "CAPS","A","S","D","F","G","H","J","K","L",":","\"","Enter",
    "[Shift]","Z","X","C","V","B","N","M","<",">","?","[Shift]", " "
  ]
  CHARACTER_TABLE_CAPS_SHIFT =
  [
    "Esc","!","@","#","$","%","^","&","*","(",")","_","+","<-Bksp",
    "~","q","w","e","r","t","y","u","i","o","p","{","}","|",
    "caps","a","s","d","f","g","h","j","k","l",":","\"","Enter",
    "[Shift]","z","x","c","v","b","n","m","<",">","?","[Shift]", " "
  ]
  #--------------------------------------------------------------------------
  # ● 定义实例变量
  #--------------------------------------------------------------------------
  attr_reader     :caps               # 是否大写锁定
  attr_reader     :shift              # 是否上档
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, window_h(3), 0, -window_h(3))
    create_contents
    @index = 0
    @caps = false
    @shift = false
    @last_index = 0
    @handler = {SHIFT => method(:update_shift)}
    activate
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 获取文字
  #--------------------------------------------------------------------------
  def character(id = -1)
    id = @index if id == -1
    if @caps
      return @shift ? CHARACTER_TABLE_CAPS_SHIFT[id] : CHARACTER_TABLE_CAPS[id]
    else
      return @shift ? CHARACTER_TABLE_SHIFT[id] : CHARACTER_TABLE_NORMAL[id]
    end
  end
  #--------------------------------------------------------------------------
  # ● 设置上档
  #--------------------------------------------------------------------------
  def shift=(shift)
    if @shift != shift
      @shift = shift
      refresh
    end
  end
  #--------------------------------------------------------------------------
  # ● 设置大写锁定
  #--------------------------------------------------------------------------
  def caps=(caps)
    if @caps != caps
      @caps = caps
      refresh
    end
  end
  #--------------------------------------------------------------------------
  # ● 获取按钮位置
  #--------------------------------------------------------------------------
  def key_pos(id)
    x = y = w = 0
    case id
    when 0..12 # Esc 1 ... =
      x, y, w = 4 + id * 40, line_height(1.5), 40
    when 13 # 退格
      x, y, w = 524, line_height(1.5), 80
    when 14..27 # ` Q W ... \
      x, y, w = 24 + (id - 14) * 40, line_height(2.5), 40
    when 28 # 大写
      x, y, w = 4, line_height(3.5), 80
    when 29..39 # A S ... '
      x, y, w = 84 + (id - 29) * 40, line_height(3.5), 40
    when 40 # 回车
      x, y, w = 524, line_height(3.5), 80
    when 41 # LShift
      x, y, w = 4, line_height(4.5), 100
    when 42..51 # Z X ... /
      x, y, w = 104 + (id - 42) * 40, line_height(4.5), 40
    when 52 # RShift
      x, y, w = 504, line_height(4.5), 100
    when 53 # 空格
      x, y, w = 184, line_height(5.5), 280
    end
    return [x, y, w, line_height]
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    for i in 0..53
      pos = key_pos(i)
      self.contents.draw_text(pos[0], pos[1], pos[2], pos[3], character(i), 1)
    end
  end
  #--------------------------------------------------------------------------
  # ● 刷新光标矩形
  #--------------------------------------------------------------------------
  def update_cursor_rect
    pos = key_pos(@index)
    self.cursor_rect.set(pos[0], pos[1], pos[2], pos[3])
  end
  #--------------------------------------------------------------------------
  # ● 光标有效判定
  #--------------------------------------------------------------------------
  def cursor_respond?
    true
  end
  #--------------------------------------------------------------------------
  # ● 刷新画面
  #--------------------------------------------------------------------------
  def update
    super
    update_cursor_rect
    update_keypress if self.active
  end
  #--------------------------------------------------------------------------
  # ● 上键处理
  #--------------------------------------------------------------------------
  def update_up(force)
    case @index
    when 0..13
      $game_system.se_play($data_system.buzzer_se)
    when 14..40
      @index -= 14
    when 41..52
      @index -= 13
    when 53
      @index = @last_index
    end   
    $game_system.se_play($data_system.cursor_se) unless @index < 14
  end
  #--------------------------------------------------------------------------
  # ● 下键处理
  #--------------------------------------------------------------------------
  def update_down(force)
    case @index
    when 0..27
      @index += 14
      @index = [@index, 40].min
    when 28..40
      @index += 13
      @index = [@index, 52].min
    when 41..52
      @last_index = @index
      @index = 53
    when 53
      $game_system.se_play($data_system.buzzer_se)
    end   
    $game_system.se_play($data_system.cursor_se) unless @index == 53
  end
  #--------------------------------------------------------------------------
  # ● 左键处理
  #--------------------------------------------------------------------------
  def update_left(force)
    case @index
    when 0, 14, 28, 41, 53
      $game_system.se_play($data_system.buzzer_se)
    else
      $game_system.se_play($data_system.cursor_se)
      @index -= 1
    end
  end
  #--------------------------------------------------------------------------
  # ● 右键处理
  #--------------------------------------------------------------------------
  def update_right(force)
    case @index
    when 13, 27, 40, 52, 53
      $game_system.se_play($data_system.buzzer_se)
    else
      $game_system.se_play($data_system.cursor_se)
      @index += 1
    end
  end
  #--------------------------------------------------------------------------
  # ● 上页处理
  #--------------------------------------------------------------------------
  def update_pageup
    $game_system.se_play($data_system.cursor_se)
    self.caps = !caps
  end
  #--------------------------------------------------------------------------
  # ● 下页处理
  #--------------------------------------------------------------------------
  def update_pagedown
    update_pageup
  end
  #--------------------------------------------------------------------------
  # ● SHIFT键处理
  #--------------------------------------------------------------------------
  def update_shift
    $game_system.se_play($data_system.cursor_se)
    self.shift = !shift
  end
end

#==============================================================================
# ■ Window_InputNumber
#==============================================================================
class Window_InputNumber < Window_Numeric
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     digits_max : 位数
  #--------------------------------------------------------------------------
  def initialize(digits_max)
    # 从数字的幅度计算(假定与 0~9 等幅)光标的幅度
    width = ((Font.default_size >> 1) + 8) * digits_max + 40
    super(0, 0, width, window_h)
    @digits_max = digits_max
    self.z += 9999
    self.opacity = 0
    @max = @magnitude ** @digits_max - 1
    refresh
    update_cursor_rect
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    change_color(normal_color)
    draw_number(4, 0)
  end
end

#==============================================================================
# ■ Window_BattleStatus
#==============================================================================
class Window_BattleStatus
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #--------------------------------------------------------------------------
  def initialize
    super(0, SCREEN_H - window_h(4), 0, window_h(4))
    self.contents = Bitmap.new(width - 32, height - 32)
    @level_up_flags = [false, false, false, false]
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    @item_max = $game_party.actors.size
    $game_party.actors.each_with_index do |actor, i|
      actor_x = i * 160 + 4
      draw_actor_name(actor, actor_x, 0)
      draw_actor_hp(actor, actor_x, line_height(1), 120)
      draw_actor_sp(actor, actor_x, line_height(2), 120)
      if @level_up_flags
        change_color(normal_color)
        draw_text(actor_x, line_height(3), 120, line_height, Vocab.level_up)
      else
        draw_actor_state(actor, actor_x, line_height(3))
      end
    end
  end
end

#==============================================================================
# ■ Window_BattleResult
#==============================================================================
class Window_BattleResult
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     exp       : EXP
  #     gold      : 金钱
  #     treasures : 宝物
  #--------------------------------------------------------------------------
  def initialize(exp, gold, treasures)
    @exp = exp
    @gold = gold
    @treasures = treasures
    super(SCREEN_W >> 2, 0, SCREEN_W >> 1, window_h(@treasures.size + 1))
    create_contents
    self.y = SCREEN_H - window_h(4) - height >> 1
    self.back_opacity = 160
    self.visible = false
    refresh
  end
  #--------------------------------------------------------------------------
  # ● 刷新
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    cx = text_size(@exp).width + text_size(Vocab.exp).width + 2
    draw_currency_value(@exp, Vocab.exp, 4, 0, cx)
    cg = text_size(@gold).width + text_size(Vocab.gold).width + 2
    draw_currency_value(@gold, Vocab.gold, 20 + cx, 0, cg)
    @treasures.each_with_index do |item, i|
      draw_item_name(item, 4, line_height(i + 1))
    end
  end
end

#==============================================================================
# ■ Window_System
#------------------------------------------------------------------------------
#   显示系统文字的窗口,该窗口会被自定义界面类调用。
#==============================================================================
class Window_System < Window_Base
  #--------------------------------------------------------------------------
  # ● 初始化对像
  #     x     : 窗口的 X 坐标
  #     y     : 窗口的 Y 坐标
  #     width : 窗口的宽度
  #     text  : 窗口的初始文字
  #--------------------------------------------------------------------------
  def initialize(x, y, width, text)
    super(x, y, width, window_h)
    set_text(text)
  end
  #--------------------------------------------------------------------------
  # ● 设置文字
  #     text  : 窗口的初始文字
  #--------------------------------------------------------------------------
  def set_text(text)
    # 如果新文字和当前文字一样就返回
    return if @text == text
    @text = text
    create_contents
    # 以系统颜色居中绘制文字
    change_color(system_color)
    draw_text(0, 0, contents.width, contents.height, text, 1)
  end
end

#==============================================================================
# ■ Scene_Base
#==============================================================================
module Scene_Base
  #--------------------------------------------------------------------------
  # ● 绑定按键事件(设置场景扩展方法8000)
  #--------------------------------------------------------------------------
  def post_create_8000
    ivar = instance_variables.map {|i| [i, instance_variable_get(i)]}
    # 自动绑定只限以下13个按键,不包括方向键和Ctrl/Alt/Shift修饰键
    keys = [:A, :B, :C, :X, :Y, :Z, :L, :R, :F5, :F6, :F7, :F8, :F9]
    ivar.each do |i|
      if i[1].is_a?(Window_Handler) or (i[1].is_a?(Array) and
        i[1][0].is_a?(Window_Handler))
        method_prefix = i[0][1...i[0].size]
        keys.each do |k|
          name = "#{method_prefix}_#{k.to_s.downcase}"
          if respond_to?(name)
            i[1].to_a.each do |window|
              window && window.set_handler(Input.const_get(k), method(name))
            end
          end
        end
      end
    end
  end
end

#==============================================================================
# ■ Scene_Title
#==============================================================================
class Scene_Title
  #--------------------------------------------------------------------------
  # ● 设置场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def post_create_2000
    @command_window.center(Rect.new(0, SCREEN_H >> 1, SCREEN_W, SCREEN_H >> 1))
    @command_window.openness = 0
    @command_window.open
  end
  #--------------------------------------------------------------------------
  # ● 终止场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def pre_terminate_2000
    Graphics.transition(0)
    @command_window.close
    until @command_window.close? do
      Graphics.update
      @command_window.update
    end
    Graphics.freeze
  end
end

#==============================================================================
# ■ Scene_Menu
#==============================================================================
class Scene_Menu
  #--------------------------------------------------------------------------
  # ● 设置场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def post_create_2000
    @command_window.align(7)
    @status_window.align(6)
    @gold_window.align(1)
    @steps_window.dock(@gold_window, 2, 1)
    @playtime_window.dock(@steps_window, 2, 1)
  end
end

#==============================================================================
# ■ Scene_End
#==============================================================================
class Scene_End
  #--------------------------------------------------------------------------
  # ● 设置场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def post_create_2000
    @command_window.center
    @command_window.openness = 0
    @command_window.open
  end
  #--------------------------------------------------------------------------
  # ● 终止场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def pre_terminate_2000
    Graphics.transition(0)
    @command_window.close
    until @command_window.close? do
      Graphics.update
      @command_window.update
    end
    Graphics.freeze
  end
end

#==============================================================================
# ■ Scene_Shop
#==============================================================================
class Scene_Shop
  #--------------------------------------------------------------------------
  # ● 设置场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def post_create_2000
    @gold_window.dock(@command_window, 4)
    start_y = @command_window.y + @command_window.height
    @dummy_window.move(0, start_y, SCREEN_W, SCREEN_H - start_y)
  end
end

#==============================================================================
# ■ Scene_Name
#==============================================================================
class Scene_Name
  #--------------------------------------------------------------------------
  # ● 刷新画面
  #--------------------------------------------------------------------------
  def update
    update_all_windows
  end
  #--------------------------------------------------------------------------
  # ● 输入A键处理
  #--------------------------------------------------------------------------
  def input_window_a
    # 名称为空的情况下
    if @edit_window.name == ""
      # 还原为默认名称
      @edit_window.restore_default
      # 名称仍然为空的情况下
      if @edit_window.name == ""
        # 演奏冻结 SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # 演奏确定 SE
      $game_system.se_play($data_system.decision_se)
      return
    end
    # 更改角色名称
    @actor.name = @edit_window.name
    # 演奏确定 SE
    $game_system.se_play($data_system.decision_se)
    # 切换到地图画面
    $scene = Scene_Map.new
  end
  #--------------------------------------------------------------------------
  # ● 输入B键处理
  #--------------------------------------------------------------------------
  def input_window_b
    # 有可以删除字符的情况下
    if @edit_window.index > 0
      # 演奏取消 SE
      $game_system.se_play($data_system.cancel_se)
      # 删除字符
      @edit_window.back
    end
  end
  #--------------------------------------------------------------------------
  # ● 输入C键处理
  #--------------------------------------------------------------------------
  def input_window_c
    # 取得光标位置
    case @input_window.character
    # 光标位置为 [取消] 的情况下
    when "Esc"
      # 还原为默认名称
      @edit_window.restore_default
    # 光标位置为 [回车] 的情况下
    when "Enter"
      input_window_a
    # 光标位置为 [退格] 的情况下
    when "<-Bksp"
      input_window_b
    # 光标位置为 [大写] 的情况下
    when "CAPS", "caps"
      # 演奏光标 SE
      $game_system.se_play($data_system.cursor_se)
      @input_window.caps = !@input_window.caps
      return
    # 光标位置为 [上档] 的情况下
    when "Shift", "[Shift]"
      # 演奏光标 SE
      $game_system.se_play($data_system.cursor_se)
      @input_window.shift = !@input_window.shift
      return
    # 其他情况下
    else
      # 光标位置为最大的情况下
      if @edit_window.index == $game_temp.name_max_char
        # 演奏冻结 SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # 文字为空的情况下
      if @input_window.character == ""
        # 演奏冻结 SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      # 演奏确定 SE
      $game_system.se_play($data_system.decision_se)
      # 添加文字
      @edit_window.add(@input_window.character)
      # 取消上档
      @input_window.shift = false if @input_window.shift
    end
  end
end

#==============================================================================
# ■ Scene_Debug
#==============================================================================
class Scene_Debug
  #--------------------------------------------------------------------------
  # ● 设置场景扩展方法处理 2000
  #--------------------------------------------------------------------------
  def post_create_2000
    @help_window.height = @help_window.window_h(3)
    @help_window.align(3)
    @help_window.create_contents
  end
  #--------------------------------------------------------------------------
  # ● 更新场景
  #--------------------------------------------------------------------------
  def update
    @right_window.mode = @left_window.mode
    @right_window.top_id = @left_window.top_id
    update_all_windows
    $game_temp.debug_top_row = @left_window.top_row
    $game_temp.debug_index = @left_window.index
  end
  #--------------------------------------------------------------------------
  # ● 左侧窗口B键处理
  #--------------------------------------------------------------------------
  def left_window_b
    # 演奏取消 SE
    $game_system.se_play($data_system.cancel_se)
    # 切换到地图画面
    $scene = Scene_Map.new
  end
  #--------------------------------------------------------------------------
  # ● 左侧窗口C键处理
  #--------------------------------------------------------------------------
  def left_window_c
    # 演奏确定 SE
    $game_system.se_play($data_system.decision_se)
    # 显示帮助
    line_height = @help_window.line_height
    if @left_window.mode == 0
      text1 = "C (Enter) : ON / OFF"
      @help_window.draw_text(4, 0, 406, line_height, text1)
    else
      text1 = "← : -1   → : +1"
      text2 = "L (PageUp) : -10  R (PageDown) : +10"
      text3 = "Shift : 100x  Ctrl : 10Kx  Alt : 100Mx"
      @help_window.draw_text(4, 0, 406, line_height, text1)
      @help_window.draw_text(4, line_height, 406, line_height, text2)
      @help_window.draw_text(4, line_height << 1, 406, line_height, text3)
    end
    # 激活右侧窗口
    @left_window.deactivate
    @right_window.activate.index = 0
  end
  #--------------------------------------------------------------------------
  # ● 右侧窗口B键处理
  #--------------------------------------------------------------------------
  def right_window_b
    # 演奏取消 SE
    $game_system.se_play($data_system.cancel_se)
    # 激活左侧窗口
    @left_window.activate
    @right_window.deactivate.index = -1
    # 删除帮助
    @help_window.contents.clear
  end
  #--------------------------------------------------------------------------
  # ● 右侧窗口C键处理
  #--------------------------------------------------------------------------
  def right_window_c
    # 开关的情况下
    if @right_window.mode == 0
      # 获取被选择的开关 / 变量的 ID
      current_id = @right_window.top_id + @right_window.index
      # 演奏确定 SE
      $game_system.se_play($data_system.decision_se)
      # 逆转 ON / OFF 状态
      $game_switches[current_id] = (not $game_switches[current_id])
      @right_window.refresh
    end
  end
end
[/pre][/fold]

范例工程已上传,欢迎测试。
WindowCore.zip (253.29 KB, 下载次数: 270)

评分

参与人数 2星屑 +200 赞 +2 收起 理由
cc610523 + 1 精品文章
RyanBern + 200 + 1 精品文章

查看全部评分

SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
梦石
0
星屑
2724
在线时间
227 小时
注册时间
2016-3-27
回帖
557
发表于 2017-12-3 11:10:28 | 显示全部楼层
默默点了收藏...感觉UI要全统一才比较好吧,不然好违和

点评

这...选怪物还有很多方法吧  发表于 2017-12-3 12:40
删掉了你还怎么打仗……  发表于 2017-12-3 12:26
不能删掉吗...或者说素材处理掉  发表于 2017-12-3 12:16
当然统一更好,不过之所以允许个别设定是因为XP有个肉疼的东西叫做Arrow....这个在windowskin里面  发表于 2017-12-3 11:29
现在还能改名吗qwq
回复

使用道具 举报

梦石
0
星屑
8498
在线时间
775 小时
注册时间
2017-11-10
回帖
1074
发表于 2017-12-3 15:40:09 | 显示全部楼层
只是窗口外观和光标发生了变化吗?
使用VA的规格windowskin,原XP的规格就不能用了对吗?

点评

双边兼容的……你想用哪个规格都可以,我这正在更新对MV规格的支持……  发表于 2017-12-3 15:54
一个只会简单事件的Rm新人,脚本完全不懂。只求做个简单的游戏完成自己的游戏之梦而已。
第一个游戏已经完成,等待各素材的完成和测试。
回复

使用道具 举报

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

 楼主| 发表于 2017-12-18 17:49:34 | 显示全部楼层
本帖最后由 SailCat 于 2017-12-18 21:28 编辑

更新完整版插件 v1.2并范例

发布的版本中将所有设置项都写成了RGSS1的默认值,也就是说,连血条阴影啥的都没有……你自己打开设置项就行了
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复

使用道具 举报

梦石
0
星屑
35248
在线时间
4171 小时
注册时间
2007-12-15
回帖
9489
发表于 2017-12-28 21:47:10 | 显示全部楼层
本帖最后由 89444640 于 2017-12-30 09:56 编辑

提个问题,这个应该在哪里改?
01.png
我查了一下,可能是SEP 插件公共核心
1894行开始
def draw_actor_exp(actor, x, y)
    contents.font.color = system_color
    contents.draw_text(x, y, 24, 32, Vocab.exp_a)
    contents.font.color = normal_color
    contents.draw_text(x + 24, y, 84, 32, actor.exp_s, 2)
    contents.draw_text(x + 108, y, 12, 32, "/", 1)
    contents.draw_text(x + 120, y, 84, 32, actor.next_exp_s)
  end
end
这段
我这里没有脚本以前,是Window_Base 220行开始改成了
def draw_actor_exp(actor, x, y)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 64, 32, "Exp:")
    txt = "#{actor.now_exp}/#{actor.next_exp}"
    cx = contents.text_size(txt).width
    self.contents.draw_text(x+64, y, cx, 32, txt)
  end
删除了SEP 插件公共核心后
显示是这样的
02.png

因为只有这段有exp描述,推测可能是这里出问题了,但是我直接把这段复制到sep核心插件会出问题,应该是#闹得,如果弄过来,让exp如图正常显示,应该怎么描述呢?
我不懂程序语法,只能慢慢蒙着实验看看怎么弄能正常显示,还请帮忙看一下。
菜单主界面底下的exp也不给描绘……
Scripts.rar (265.83 KB, 下载次数: 71)

我改了很多次都没变化,因为眼中菜单冲突,范例中脚本3~5都没法用。

全局搜索,替换所有脚本中出现的两个词组为后面的,
01.jpg
然后毅然只能显示成XXX/XXXX
前面的数字只能显示后三位,第四位无法显示。
真的不知道该怎么弄了。

刚才看了game actor,发现行数与默认不一样,于是挨个找
发现这里
02.png
与默认脚本不一样
01.png
应该是什么时候动过,我试着改一下看看。

改了以后还是不行,然后接着一行一行的对着看哪里动过。
发现windows status动过,而且还没少动。行数查了好多。
于是一行一行的找,发现了这里应该是描述exp的地方了。
03.png
于是对着默认脚本看把最有可能的脚本复制过来。
终于成功了T T
04.png

真是得多谢楼主,辛苦了。

点评

确实windows status问题,改回默认的描述后终于正常了,上面的图像就是正常后的显示。  发表于 2017-12-30 22:13
看起来并不是这里的问题,你需要查一下Window_Status里面关于描绘这里的部分。  发表于 2017-12-30 21:56
对着默认脚本挨个找,发现Window_Status也有人动过没注明,我一般动过的脚本都注明(改),可能是这里造成的?我试着弄一下。  发表于 2017-12-30 09:43
Game_Actor 里面也有一处 345 355 def next_exp_s return @exp_list[@level+1] > 0 ? @exp_list[@level+1].to_s : "-------"  发表于 2017-12-30 09:17
最后一处 sep 1900 contents.draw_text(x + 120, y, 84, 32, actor.next_exp_s)  发表于 2017-12-30 09:16
回复

使用道具 举报

梦石
0
星屑
504
在线时间
43 小时
注册时间
2018-2-19
回帖
60
发表于 2018-3-10 03:08:51 | 显示全部楼层
真好用,感谢楼主分享。
梦想是谁创造的,梦想是自己创造的。站起来吧。
                      梦想由我们自己来创造。
  无论未来有多么困难,在下都会尽全力走下去。
回复

使用道具 举报

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

 楼主| 发表于 2018-8-26 22:52:47 | 显示全部楼层
更新v1.6 update
回复

使用道具 举报

梦石
0
星屑
4638
在线时间
488 小时
注册时间
2017-7-7
回帖
134

R考场第七期纪念奖

发表于 2018-9-6 23:27:36 | 显示全部楼层
本帖最后由 Six_Fish 于 2018-9-6 23:38 编辑

报告猫姐,v1.6版本的核心使用对话增强疯狂报错
-
经排查是使用\[人名框]功能后出错

点评

686和687行的@back_opacity改为self.back_opacity,我忽略了,上面都做了定义,这里要按照属性来取,以免子类重定义的时候出问题。  发表于 2018-9-7 00:10
贴错误信息  发表于 2018-9-6 23:48
回复

使用道具 举报

遠航の猫咪

梦石
3
星屑
26947
在线时间
2423 小时
注册时间
2005-10-15
回帖
987

开拓者

 楼主| 发表于 2018-9-7 01:10:43 | 显示全部楼层
更新v1.7 修正了一个兼容性bug
感谢@Six_Fish 测试汇报
SailCat (小猫子·要开心一点) 共上站 24 次,发表过 11 篇文章 上 次 在: [2006年01月28日11:41:18 星期六] 从 [162.105.120.91] 到本站一游。
回复

使用道具 举报

梦石
0
星屑
35248
在线时间
4171 小时
注册时间
2007-12-15
回帖
9489
发表于 2020-8-3 16:54:10 | 显示全部楼层
猫大,窗口增强-对话窗口v1.1 刷新画面:按键跳过 部分发现一个bug
01.png
在按B 取消键跳过对话的时候,如果我对话中有显示选项,并且是取消无效的情况,就会直接跳出,而不是默认的无法关闭对话框并且播放无效的音效,
请问怎么修正?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部