#============================================================================== # ★ RGSS3_荣誉系统 Ver1.00 #============================================================================== #尼玛啊!!!我讨厌日文啊 #使用方法: # gain_medal(0) #============================================================================== # □ 设定项目 #============================================================================== module TMMEDAL COMMAND_MEDAL = "成就" # 菜单中的名字 # 一个荣誉也没有时隐藏菜单(true隐藏;false不隐藏) HIDE_COMMAND = false # 荣誉获得时的效果音 SE_GAIN_MEDAL = RPG::SE.new("Powerup", 90, 140) # 荣誉名称及简介的设置 #例如:MEDAL_DATA[0] = ["名字", 187(icon), "简介"] MEDAL_DATA = {} MEDAL_DATA[0] = ["名字?", 187, "简介?"] MEDAL_DATA[1] = ["探索者", **, "第一次找到隐藏地点"] MEDAL_DATA[2] = [" ", 190, ""] end #============================================================================== # ■ Game_Party #============================================================================== class Game_Party #-------------------------------------------------------------------------- # ● 公開インスタンス変数 #-------------------------------------------------------------------------- attr_reader :medals # 獲得済みメダル attr_reader :new_medals # 新規獲得メダル attr_accessor :medal_info_count # メダル情報表示カウント attr_accessor :medal_info_opacity # メダル情報表示不透明度 #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- alias tmmedal_game_party_initialize initialize def initialize tmmedal_game_party_initialize @medals = [] @new_medals = [] @medal_info_count = 0 @medal_info_opacity = 0 end #-------------------------------------------------------------------------- # ○ メダルの獲得 #-------------------------------------------------------------------------- def gain_medal(medal_id) return if @medals.any? {|medal| medal[0] == medal_id } t = Time.now.strftime(" (%Y/%m/%d %H:%M)") @medals.push([medal_id, t]) @new_medals.push([medal_id, t]) end #-------------------------------------------------------------------------- # ○ 獲得メダル情報の消去 #-------------------------------------------------------------------------- def delete_new_medal @new_medals.shift end end #============================================================================== # ■ Game_Interpreter #============================================================================== class Game_Interpreter #-------------------------------------------------------------------------- # ○ メダルの獲得 #-------------------------------------------------------------------------- def gain_medal(medal_id) $game_party.gain_medal(medal_id) end end #============================================================================== # ■ Window_MenuCommand #============================================================================== class Window_MenuCommand #-------------------------------------------------------------------------- # ● 独自コマンドの追加用 #-------------------------------------------------------------------------- alias tmmedal_window_menucommand_add_original_commands add_original_commands def add_original_commands tmmedal_window_menucommand_add_original_commands unless TMMEDAL::HIDE_COMMAND && !medal_enabled add_command(TMMEDAL::COMMAND_MEDAL, :medal, medal_enabled) end end #-------------------------------------------------------------------------- # ○ メダルの有効状態を取得 #-------------------------------------------------------------------------- def medal_enabled !$game_party.medals.empty? end end #============================================================================== # □ Window_MedalInfo #============================================================================== class Window_MedalInfo < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super(Graphics.width - window_width, 0, window_width, fitting_height(1)) self.opacity = 0 self.contents_opacity = $game_party.medal_info_opacity refresh end #-------------------------------------------------------------------------- # ● ウィンドウ幅の取得 #-------------------------------------------------------------------------- def window_width return 240 end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super if $game_party.medal_info_count > 0 self.contents_opacity += 16 $game_party.medal_info_count -= 1 $game_party.delete_new_medal if $game_party.medal_info_count == 0 else self.contents_opacity -= 16 if self.contents_opacity == 0 open unless $game_party.new_medals.empty? end end $game_party.medal_info_opacity = self.contents_opacity end #-------------------------------------------------------------------------- # ● ウィンドウを開く #-------------------------------------------------------------------------- def open refresh TMMEDAL::SE_GAIN_MEDAL.play $game_party.medal_info_count = 150 self.contents_opacity = 0 self end #-------------------------------------------------------------------------- # ○ リフレッシュ #-------------------------------------------------------------------------- def refresh contents.clear unless $game_party.new_medals.empty? draw_background(contents.rect) medal = TMMEDAL::MEDAL_DATA[$game_party.new_medals[0][0]] rect = contents.rect.clone draw_icon(medal[1], rect.x, rect.y) rect.x += 24 rect.width -= 24 draw_text(rect, medal[0]) end end #-------------------------------------------------------------------------- # ○ 背景の描画 #-------------------------------------------------------------------------- def draw_background(rect) temp_rect = rect.clone temp_rect.width /= 2 contents.gradient_fill_rect(temp_rect, back_color2, back_color1) temp_rect.x = temp_rect.width contents.gradient_fill_rect(temp_rect, back_color1, back_color2) end #-------------------------------------------------------------------------- # ○ 背景色 1 の取得 #-------------------------------------------------------------------------- def back_color1 Color.new(0, 0, 0, 192) end #-------------------------------------------------------------------------- # ○ 背景色 2 の取得 #-------------------------------------------------------------------------- def back_color2 Color.new(0, 0, 0, 0) end end #============================================================================== # □ Window_Medal #============================================================================== class Window_Medal < Window_Selectable #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(x, y, width, height) super refresh select(0) activate end #-------------------------------------------------------------------------- # ● 桁数の取得 #-------------------------------------------------------------------------- def col_max return 1 end #-------------------------------------------------------------------------- # ● 項目数の取得 #-------------------------------------------------------------------------- def item_max @data ? @data.size : 1 end #-------------------------------------------------------------------------- # ● アイテムの取得 #-------------------------------------------------------------------------- def item @data && index >= 0 ? @data[index] : nil end #-------------------------------------------------------------------------- # ● アイテムリストの作成 #-------------------------------------------------------------------------- def make_item_list @data = $game_party.medals end #-------------------------------------------------------------------------- # ● 項目の描画 #-------------------------------------------------------------------------- def draw_item(index) item = @data[index] medal = TMMEDAL::MEDAL_DATA[item[0]] rect = item_rect(index) draw_icon(medal[1], rect.x, rect.y) rect.x += 24 rect.width -= 216 draw_text(rect, medal[0]) rect.x = contents.width - 192 rect.width = 192 draw_text(rect, item[1], 2) end #-------------------------------------------------------------------------- # ● ヘルプテキスト更新 #-------------------------------------------------------------------------- def update_help if item medal = TMMEDAL::MEDAL_DATA[item[0]] text = medal[2] @help_window.set_text(text) end end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh make_item_list create_contents draw_all_items end end #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map #-------------------------------------------------------------------------- # ● 全ウィンドウの作成 #-------------------------------------------------------------------------- alias tmmedal_scene_map_create_all_windows create_all_windows def create_all_windows tmmedal_scene_map_create_all_windows create_medal_window end #-------------------------------------------------------------------------- # ○ メダルウィンドウの作成 #-------------------------------------------------------------------------- def create_medal_window @medal_window = Window_MedalInfo.new end end #============================================================================== # ■ Scene_Menu #============================================================================== class Scene_Menu #-------------------------------------------------------------------------- # ● コマンドウィンドウの作成 #-------------------------------------------------------------------------- alias tmmedal_scene_menu_create_command_window create_command_window def create_command_window tmmedal_scene_menu_create_command_window @command_window.set_handler(:medal, method(:command_medal)) end #-------------------------------------------------------------------------- # ○ コマンド[メダル] #-------------------------------------------------------------------------- def command_medal SceneManager.call(Scene_Medal) end end #============================================================================== # □ Scene_Medal #============================================================================== class Scene_Medal < Scene_MenuBase #-------------------------------------------------------------------------- # ● 開始処理 #-------------------------------------------------------------------------- def start super create_help_window create_item_window end #-------------------------------------------------------------------------- # ○ アイテムウィンドウの作成 #-------------------------------------------------------------------------- def create_item_window wy = @help_window.height wh = Graphics.height - wy @item_window = Window_Medal.new(0, wy, Graphics.width, wh) @item_window.viewport = @viewport @item_window.help_window = @help_window @item_window.set_handler(:cancel, method(:return_scene)) end end
#============================================================================== # [PS0]截图存档 # Window_SaveFile_Plus #------------------------------------------------------------------------------ # 一种带有截图的存档,同时可以自定义存档数量。 #============================================================================== # [核心脚本] # - 快速储存Bitmap的Marshal By 柳之一 #------------------------------------------------------------------------------ # [更新记录] # - 2012.02.16 By 各种压力的猫君 # * 修正地图边缘时截图不完整的错误 # - 2012.01.28 By 各种压力的猫君 # * 去掉效率较差的双线性缩放算法; # * 新增存档管理功能(F5键,复制/移动/删除存档) # - 2011.12.27 By 各种压力的猫君 # * 补上截图阴影; # * 新增“不缩放”截图(推荐使用,尤其是大分辨率); # * 修正选择不存在的存档时存档列表窗口卡死以及奇怪的SE; # * 新增“存档中”提示窗口、覆盖存档提示、删除存档功能(Z键,对应键盘D) # - 2011.12.26 By 各种压力的猫君 # * 功能齐全的测试版 # - 2011.12.16 By 各种压力的猫君 # * 移植至RGSS3,遵循PS0协议; # * 丰富自定义选项,整合双线性插值算法精简版 # - 2008.05.26 By 沉影不器 # * 蓝本(VX新截图存档) #------------------------------------------------------------------------------ # [使用方法] # - 删除原Scene_File、Window_SaveFile 并将本脚本插入到原Scene_File位置。 # - 或者直接将本脚本插入到MAIN以上,并确保本脚本位于上述两个脚本以下。 #============================================================================== $_PS0 = {} if $_PS0 == nil $_PS0["Window_SaveFile_Plus"] = 20120216 #============================================================================== # [PS0] 通用配置模块 #============================================================================== module PS0 module Window_SaveFile_Plus # 最大存档数(范围正整数) MAX_SAVE = 18 # 存档目录(默认值 "Saves/";根目录 "") SAVE_DIR = "Saves/" # 无存档时显示的文字 NO_DATA = "无存档" # 保存时显示的信息 SAVE_NOW = "存档中..." # 复制存档时的帮助文字 HELP_COPY = "要复制到哪个位置?" # 移动存档时的帮助文字 HELP_MOVE = "要移动到哪个位置?" # 是否显示存档中窗口(true:显示;false:不显示) # - 分辨率较大时建议显示 SHOW_SAVE_NOW = false # 截图缩放使用的插值算法 # - "NN" 最邻近(速度最快,质量最差,RM默认算法) # - "NZ" 不缩放(速度快,质量好,以主角为中心切边,非全屏) Zoom_Type = "NZ" # 双线性插值能获得更好的截图缩放质量,但所需时间较最邻近插值更长。 # 缩略图尺寸(范围整数,单位像素) # - VA默认分辨率(544×416)推荐使用340×260 # - VA最大分辨率(640×480)推荐使用425×325 # - 本脚本兼容分辨率解放,窗口大小将自动计算。 # 请自行计算截图分辨率,注意要确保宽高比一致, # 若使用“不缩放”模式则可以不保持一致。 Thumbnail_Width = 340 # 宽度 Thumbnail_Height = 260 # 高度 # 缩略图位置微调(范围整数,单位像素) Thumbnail_ox = -2 # 横向 Thumbnail_oy = -2-32 # 纵向 # 各窗口切换时的渐变帧数 TRANS_DURATION = 5 end end #============================================================================== # [核心脚本] 快速储存Bitmap的Marshal By 柳之一 #============================================================================== class Font def marshal_dump end def marshal_load(obj) end end class Bitmap RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i') RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i') def _dump(limit) data = "rgba" * width * height RtlMoveMemory_pi.call(data, address, data.length) [width, height, Zlib::Deflate.deflate(data)].pack("LLa*") end def self._load(str) w, h, zdata = str.unpack("LLa*") b = self.new(w, h) RtlMoveMemory_ip.call(b.address, Zlib::Inflate.inflate(zdata), w * h * 4) return b end def address buffer, ad = "rgba", object_id * 2 + 16 RtlMoveMemory_pi.call(buffer, ad, 4) ad = buffer.unpack("L")[0] + 8 RtlMoveMemory_pi.call(buffer, ad, 4) ad = buffer.unpack("L")[0] + 16 RtlMoveMemory_pi.call(buffer, ad, 4) return buffer.unpack("L")[0] end end #============================================================================== # ■ Game_Temp #============================================================================== class Game_Temp attr_accessor :save_bitmap attr_accessor :save_snapshoot alias new_initialize initialize def initialize new_initialize @save_bitmap = Bitmap.new(1, 1) @save_snapshoot = Bitmap.new(1, 1) end end #============================================================================== # ■ SceneManager #============================================================================== module SceneManager def self.snapshot_for_save $game_temp.save_bitmap = Graphics.snap_to_bitmap unless FileTest.exist?(PS0::Window_SaveFile_Plus::SAVE_DIR) Dir.mkdir(PS0::Window_SaveFile_Plus::SAVE_DIR) end end end #============================================================================== # ■ Scene_Map #============================================================================== class Scene_Map < Scene_Base alias save_terminate terminate def terminate SceneManager.snapshot_for_save save_terminate end end #============================================================================== # ■ DataManager #============================================================================== module DataManager def self.save_file_exists? !Dir.glob(PS0::Window_SaveFile_Plus::SAVE_DIR + 'Save*.rvdata2').empty? end def self.make_filename(index) sprintf(PS0::Window_SaveFile_Plus::SAVE_DIR + "Save%02d.rvdata2", index + 1) end #-------------------------------------------------------------------------- # ● セーブヘッダの作成 #-------------------------------------------------------------------------- def self.make_save_header d_rect = Rect.new(0, 0, PS0::Window_SaveFile_Plus::Thumbnail_Width, PS0::Window_SaveFile_Plus::Thumbnail_Height) case PS0::Window_SaveFile_Plus::Zoom_Type when "NN" s_rect = $game_temp.save_bitmap.rect $game_temp.save_snapshoot = Bitmap.new(d_rect.width, d_rect.height) $game_temp.save_snapshoot.stretch_blt(d_rect, $game_temp.save_bitmap, s_rect) when "NZ" x = [$game_player.screen_x - d_rect.width/2, 0].max x = [x, Graphics.width - d_rect.width].min y = [$game_player.screen_y - d_rect.height/2, 0].max y = [y, Graphics.height - d_rect.height].min s_rect = Rect.new(x, y, d_rect.width, d_rect.height) $game_temp.save_snapshoot = Bitmap.new(d_rect.width, d_rect.height) $game_temp.save_snapshoot.blt(0, 0, $game_temp.save_bitmap, s_rect) end header = {} header[:characters] = $game_party.characters_for_savefile header[:playtime_s] = $game_system.playtime_s header[:snapshoot] = $game_temp.save_snapshoot header end #-------------------------------------------------------------------------- # ● セーブの実行 #-------------------------------------------------------------------------- def self.save_game(index) saving_window = Window_Saving.new Graphics.update begin save_game_without_rescue(index) rescue delete_save_file(index) false end saving_window.dispose return true end end #============================================================================== # ■ Window_Yes_Or_No #------------------------------------------------------------------------------ # 提供“是”、“否”两个选项的窗口(替换、删除存档用) #============================================================================== class Window_Yes_Or_No < Window_HorzCommand #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize(yes, no) [url=home.php?mod=space&uid=40913]@yes[/url] = yes @no = no super(130, 0) self.visible = false self.active = false @index = 0 end #-------------------------------------------------------------------------- # ● 桁数の取得 #-------------------------------------------------------------------------- def col_max return 2 end #-------------------------------------------------------------------------- # ● コマンドリストの作成 #-------------------------------------------------------------------------- def make_command_list add_command(@yes, :yes) add_command(@no, :cancel) end #-------------------------------------------------------------------------- # ● 決定ボタンが押されたときの処理 #-------------------------------------------------------------------------- def process_ok Input.update call_ok_handler end #-------------------------------------------------------------------------- # ● 按下取消键时的处理 #-------------------------------------------------------------------------- def process_cancel Input.update call_cancel_handler end #-------------------------------------------------------------------------- # ● 启用窗口 #-------------------------------------------------------------------------- def activate temp = self.y + self.height - Graphics.height if temp > 0 self.y -= (temp + 12) end self.active = true self end end #============================================================================== # ■ Window_Saving #------------------------------------------------------------------------------ # 显示保存信息的窗口 #============================================================================== class Window_Saving < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize w = PS0::Window_SaveFile_Plus::SAVE_NOW.length * 16 + 32 x = (Graphics.width - w)/2 y = (Graphics.height - fitting_height(1))/2 super(x, y, w, fitting_height(1)) self.visible = PS0::Window_SaveFile_Plus::SHOW_SAVE_NOW draw_text_ex(4, 0, PS0::Window_SaveFile_Plus::SAVE_NOW) end end #============================================================================== # ■ Window_SaveManagerCommand #------------------------------------------------------------------------------ # 存档管理窗口 #============================================================================== class Window_SaveManagerCommand < Window_Command #-------------------------------------------------------------------------- # ● 初始化对象 #-------------------------------------------------------------------------- def initialize(*args) @copy, @move, @delete, [url=home.php?mod=space&uid=9053]@cancel[/url] = args[0..3] super(130, 0) self.visible = false self.active = false @index = 0 end #-------------------------------------------------------------------------- # ● 获取窗口的宽度 #-------------------------------------------------------------------------- def window_width return 100 end #-------------------------------------------------------------------------- # ● 获取项目数 #-------------------------------------------------------------------------- def item_max return 4 end #-------------------------------------------------------------------------- # ● 生成指令列表 #-------------------------------------------------------------------------- def make_command_list add_command(@copy, :copy ) add_command(@move, :move ) add_command(@delete, :delete) add_command(@cancel, :cancel) end #-------------------------------------------------------------------------- # ● 按下确定键时的处理 #-------------------------------------------------------------------------- def process_ok Input.update call_ok_handler end #-------------------------------------------------------------------------- # ● 启用窗口 #-------------------------------------------------------------------------- def activate temp = self.y + self.height - Graphics.height if temp > 0 self.y -= (temp + 12) end self.active = true self end end #============================================================================== # ■ Window_FileCommand #------------------------------------------------------------------------------ # 截图存档左侧的选择窗口。 #============================================================================== class Window_FileCommand < Window_Command #-------------------------------------------------------------------------- # ● オブジェクト初期化 #-------------------------------------------------------------------------- def initialize super(0, 0) end #-------------------------------------------------------------------------- # ● ウィンドウ幅の取得 #-------------------------------------------------------------------------- def window_height return Graphics.height-fitting_height(1) end #-------------------------------------------------------------------------- # ● 表示行数の取得 #-------------------------------------------------------------------------- def visible_line_number item_max end #-------------------------------------------------------------------------- # ● コマンドリストの作成 #-------------------------------------------------------------------------- def make_command_list add_main_commands end #-------------------------------------------------------------------------- # ● 主要コマンドをリストに追加 #-------------------------------------------------------------------------- def add_main_commands for i in 1..PS0::Window_SaveFile_Plus::MAX_SAVE if i < 10 text = Vocab::File + " 0" + i.to_s else text = Vocab::File + " " + i.to_s end add_command(text, :file) end end #-------------------------------------------------------------------------- # ● 決定ボタンが押されたときの処理 #-------------------------------------------------------------------------- def process_ok end end #============================================================================== # ■ Window_SaveFile #------------------------------------------------------------------------------ # セーブ画面およびロード画面で表示する、セーブファイルのウィンドウです。 #============================================================================== class Window_SaveFile < Window_Base #-------------------------------------------------------------------------- # ● オブジェクト初期化 # index : セーブファイルのインデックス #-------------------------------------------------------------------------- def initialize(index) super(160, 0, Graphics.width-160, Graphics.height-fitting_height(1)) @file_index = index @selected = true refresh end #-------------------------------------------------------------------------- # ● リフレッシュ #-------------------------------------------------------------------------- def refresh contents.clear change_color(normal_color) w = (self.width-PS0::Window_SaveFile_Plus::Thumbnail_Width-16)/2 h = (self.height-PS0::Window_SaveFile_Plus::Thumbnail_Height-16)/2 width = w + PS0::Window_SaveFile_Plus::Thumbnail_ox height = h + PS0::Window_SaveFile_Plus::Thumbnail_oy draw_shadow(width+5, height+5) draw_text((self.width-32-PS0::Window_SaveFile_Plus::NO_DATA.length*16)/2, self.height/2-32, PS0::Window_SaveFile_Plus::NO_DATA.length*32, line_height, PS0::Window_SaveFile_Plus::NO_DATA) draw_party_characters(32, Graphics.height-fitting_height(1)-32) draw_playtime(-10, contents.height - line_height-10, contents.width - 4, 2) draw_snapshoot(width, height) end #-------------------------------------------------------------------------- # ● パーティキャラの描画 #-------------------------------------------------------------------------- def draw_party_characters(x, y) header = DataManager.load_header(@file_index) return unless header header[:characters].each_with_index do |data, i| draw_character(data[0], data[1], x + i * 48, y) end end #-------------------------------------------------------------------------- # ● プレイ時間の描画 #-------------------------------------------------------------------------- def draw_playtime(x, y, width, align) header = DataManager.load_header(@file_index) return unless header draw_text(x, y, width, line_height, header[:playtime_s], 2) end #-------------------------------------------------------------------------- # ● 绘制截图 #-------------------------------------------------------------------------- def draw_snapshoot(x, y) header = DataManager.load_header(@file_index) return unless header bitmap = header[:snapshoot] contents.blt(x, y, bitmap, bitmap.rect) bitmap.dispose end #-------------------------------------------------------------------------- # ● 绘制阴影 #-------------------------------------------------------------------------- def draw_shadow(x, y) header = DataManager.load_header(@file_index) return unless header contents.fill_rect(x, y, PS0::Window_SaveFile_Plus::Thumbnail_Width, PS0::Window_SaveFile_Plus::Thumbnail_Height, Color.new(0, 0, 0)) contents.blur end end #============================================================================== # ■ Scene_File #------------------------------------------------------------------------------ # セーブ画面とロード画面の共通処理を行うクラスです。 #============================================================================== class Scene_File < Scene_MenuBase #-------------------------------------------------------------------------- # ● 開始処理 #-------------------------------------------------------------------------- def start super create_help_window create_savefile_viewport create_command_window create_savefile_window create_manager_window create_replace_window create_delete_window end #-------------------------------------------------------------------------- # ● 終了処理 #-------------------------------------------------------------------------- def terminate super @savefile_viewport.dispose @savefile_window.dispose @command_window.dispose @window_manager.dispose @window_replace.dispose @window_delete.dispose end #-------------------------------------------------------------------------- # ● フレーム更新 #-------------------------------------------------------------------------- def update super update_savefile_selection end #-------------------------------------------------------------------------- # ● 创建替换窗口 #-------------------------------------------------------------------------- def create_replace_window @window_replace = Window_Yes_Or_No.new("替换", "取消") @window_replace.set_handler(:yes, method(:do_replace)) @window_replace.set_handler(:cancel, method(:do_cancel)) end #-------------------------------------------------------------------------- # ● 创建删除窗口 #-------------------------------------------------------------------------- def create_delete_window @window_delete = Window_Yes_Or_No.new("删除", "取消") @window_delete.set_handler(:yes, method(:do_delete)) @window_delete.set_handler(:cancel, method(:do_return_manager)) @window_delete.x += 40 end #-------------------------------------------------------------------------- # ● 创建管理窗口 #-------------------------------------------------------------------------- def create_manager_window @window_manager = Window_SaveManagerCommand.new("复制", "移动", "删除", "取消") @window_manager.set_handler(:copy , method(:on_copy?)) @window_manager.set_handler(:move , method(:on_move?)) @window_manager.set_handler(:delete, method(:on_delete?)) @window_manager.set_handler(:cancel, method(:do_cancel)) end #-------------------------------------------------------------------------- # ● ヘルプウィンドウの作成 #-------------------------------------------------------------------------- def create_help_window @help_window = Window_Help.new(1) @help_window.set_text(help_window_text) end #-------------------------------------------------------------------------- # ● ヘルプウィンドウのテキストを取得 #-------------------------------------------------------------------------- def help_window_text return "" end #-------------------------------------------------------------------------- # ● セーブファイルビューポートの作成 #-------------------------------------------------------------------------- def create_savefile_viewport @savefile_viewport = Viewport.new @savefile_viewport.rect.y = @help_window.height @savefile_viewport.rect.height -= @help_window.height end #-------------------------------------------------------------------------- # ● セーブファイルウィンドウの作成 #-------------------------------------------------------------------------- def create_savefile_window @savefile_window = Window_SaveFile.new(@index) @savefile_window.viewport = @savefile_viewport end #-------------------------------------------------------------------------- # ● 生成存档列表窗口 #-------------------------------------------------------------------------- def create_command_window @command_window = Window_FileCommand.new @command_window.index = first_savefile_index @index = @command_window.index @command_window.viewport = @savefile_viewport @command_window.set_handler(:file, method(:on_savefile_ok)) end #-------------------------------------------------------------------------- # ● セーブファイル選択の更新 #-------------------------------------------------------------------------- def update_savefile_selection if @source_index != nil if Input.trigger?(:C) if @index == @source_index Sound.play_buzzer elsif FileTest.exist?(DataManager.make_filename(@index)) Graphics.freeze @command_window.deactivate @window_replace.y = 72 + @index * 24 @window_replace.activate @window_replace.visible = true @window_replace.refresh Sound.play_ok Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) else return on_copy_ok end elsif Input.trigger?(:B) return do_return_manager end else if Input.trigger?(:C) if self.is_a?(Scene_Save) and FileTest.exist?(DataManager.make_filename(@index)) Graphics.freeze @command_window.deactivate @window_replace.y = 72 + @index * 24 @window_replace.activate @window_replace.visible = true @window_replace.refresh Sound.play_ok Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) else return on_savefile_ok end elsif Input.trigger?(:B) return on_savefile_cancel elsif Input.trigger?(:F5) unless @window_manager.active == true or @window_delete.active == true or @window_replace.active == true return on_manager? end end end @need_refresh = true if @index != @command_window.index if @need_refresh Graphics.freeze @index = @command_window.index @savefile_window.dispose create_savefile_window @need_refresh = false Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) end end #-------------------------------------------------------------------------- # ● セーブファイル[決定] #-------------------------------------------------------------------------- def on_savefile_ok end #-------------------------------------------------------------------------- # ● セーブファイル[キャンセル] #-------------------------------------------------------------------------- def on_savefile_cancel Sound.play_cancel return_scene end #-------------------------------------------------------------------------- # ● セーブファイル[決定] #-------------------------------------------------------------------------- def on_copy_ok Graphics.freeze source_name = DataManager.make_filename(@source_index) new_name = DataManager.make_filename(@index) case @source_type when "copy" # 复制存档文件(API) Win32API.new('kernel32',"CopyFileA",'ppl','').call(source_name,new_name,0) when "move" # 重命名存档 File.rename(source_name, new_name) end # 返回 @help_window.set_text(help_window_text) @source_index = nil do_return_savelist end #-------------------------------------------------------------------------- # ● セーブファイル[复制] #-------------------------------------------------------------------------- def on_copy? Graphics.freeze @help_window.set_text(PS0::Window_SaveFile_Plus::HELP_COPY) @source_index = @index @source_type = "copy" do_return_savelist end #-------------------------------------------------------------------------- # ● セーブファイル[移动] #-------------------------------------------------------------------------- def on_move? Graphics.freeze @help_window.set_text(PS0::Window_SaveFile_Plus::HELP_MOVE) @source_index = @index @source_type = "move" do_return_savelist end #-------------------------------------------------------------------------- # ● セーブファイル[管理] #-------------------------------------------------------------------------- def on_manager? if FileTest.exist?(DataManager.make_filename(@index)) Graphics.freeze @command_window.deactivate @window_manager.y = 72 + @index * 24 @window_manager.activate @window_manager.visible = true @window_manager.refresh Sound.play_ok Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) else Sound.play_buzzer end end #-------------------------------------------------------------------------- # ● セーブファイル[删除] #-------------------------------------------------------------------------- def on_delete? Graphics.freeze @window_manager.deactivate @command_window.deactivate @window_delete.y = 72 + 72 + @index * 24 @window_delete.activate @window_delete.visible = true @window_delete.refresh Sound.play_ok Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) end #-------------------------------------------------------------------------- # ● 删除 #-------------------------------------------------------------------------- def do_delete Graphics.freeze File.delete(DataManager.make_filename(@index)) @window_delete.index = 0 @window_manager.index = 0 @window_delete.visible = false @window_manager.visible = false @window_delete.deactivate @window_manager.deactivate @command_window.activate @need_refresh = true Sound.play_save if DataManager.save_file_exists? Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) else return_scene end end #-------------------------------------------------------------------------- # ● 替换 #-------------------------------------------------------------------------- def do_replace Graphics.freeze if @source_index != nil return on_copy_ok else return on_savefile_ok end @window_replace.visible = false @window_replace.deactivate @need_refresh = true end #-------------------------------------------------------------------------- # ● 取消 #-------------------------------------------------------------------------- def do_cancel Graphics.freeze Sound.play_cancel @window_delete.index = 0 @window_replace.index = 0 @window_manager.index = 0 @window_delete.visible = false @window_replace.visible = false @window_manager.visible = false @window_delete.deactivate @window_replace.deactivate @window_manager.deactivate @command_window.activate Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) end #-------------------------------------------------------------------------- # ● 返回管理菜单 #-------------------------------------------------------------------------- def do_return_manager Graphics.freeze @help_window.set_text(help_window_text) @command_window.index = @source_index unless @source_index == nil @source_index = nil @source_type = nil @command_window.deactivate @window_delete.index = 0 @window_replace.index = 0 @window_delete.visible = false @window_replace.visible = false @window_delete.deactivate @window_replace.deactivate @window_manager.y = 72 + @index * 24 @window_manager.activate @window_manager.visible = true @window_manager.refresh Sound.play_cancel Graphics.transition(PS0::Window_SaveFile_Plus::TRANS_DURATION) end #-------------------------------------------------------------------------- # ● 返回文件列表(复制、移动 用) #-------------------------------------------------------------------------- def do_return_savelist @window_manager.visible = false @window_manager.deactivate @command_window.activate @need_refresh = true Sound.play_ok end end #============================================================================== # [PS0] End of Script #==============================================================================
=begin #=============================================================================== Title: Map Screenshot Author: Tsukihime Date: Apr 15, 2013 -------------------------------------------------------------------------------- ** Change log Apr 15, 2013 - updated script to use GDI+ interface - added support for region map overlay and passage map overlay Apr 6, 2013 - fixed bug where drawing events crashed the game Apr 2, 2013 - map data is now setup by an instance of Game_Map, to account for custom map scripts adding to the map Jul 27 - Export dirNames are now optional May 28 - updated overlay mapping compatibility to draw the overlays based on the player's current position - fixed issue where import hash was commented out - Added support for Yami's overlay mapping May 24, 2012 - fixed large characters - some optimizations for calculating bounds and dimensions May 5, 2012 - fixed waterfall autotile - added screenshot feature May 4, 2012 - fixed tiles with alpha channel - fixed shadows - fixed wall autotiles May 1, 2012 - fixed wall autotile, although there is still an issue with some tiles Apr 29, 2012 - fixed shadow map drawing - added region highlighting - added damage tile highlighting Apr 28, 2012 - Initial Release ------------------------------------------------------------------------------ ** Description This script allows you to take a full image of any of your game's maps and export. An image of the map is referred to as a "mapshot" (as opposed to screenshot). The script provides various configuration options to control what kinds of things you want to see on your map, such as events, vehicles, region ID's, or specific tile properties. ------------------------------------------------------------------------------ ** Usage The default key for taking a mapshot is F7. This can be changed in the configuration section. To take a mapshot, first start the game, and then hit F7. A message will appear informing you that a mapshot was successfully taken. Alternatively, you can use script calls to take mapshots. Map_Saver.new(map_id).export Aside from exporting images, you are able to use the image that the map saver captures. ms = Map_Saver.new(map_id) bmp = ms.map_image This gives you a reference to a Bitmap object that contains an image of your map. -------------------------------------------------------------------------------- ** Credits Cremno -GDI+ interface code Cidiomar -for drawing autotiles and shadows, -providing efficient bmp and png exporters Moon -auto-tile related info Mephistox -testing and suggestions ================================================================================ =end $imported = {} if $imported.nil? $imported["TH_MapSaver"] = true #=============================================================================== # ** Configuration #=============================================================================== module TH module Map_Saver #Mapshot options. This takes an image of the entire map Mapshot_Button = Input::F7 Mapshot_Scale = 1 #Screenshot options. This takes an image of the visible map Screenshot_Button = Input::F6 Screenshot_Scale = 1 #Folder that the map will be exported to Mapshot_Directory = "Mapshots" Screenshot_Directory = "Screenshots" # format you want to export to. You should stick with png. # Options: [bmp, png] Export_Format = "png" # Sprite draw options Draw_Events = false Draw_Player = false Draw_Followers = false Draw_Vehicles = false #Should shadows be drawn? What color? Draw_Shadow = true Shadow_Color = Color.new(0, 0, 0, 128) # Should regions be drawn? Requires "Region Overlay Map" script Draw_Regions = false # Should passage settings be drawn? Requires "Passage Overlay Map" script Draw_Passages = false #Should damage tiles be highlighted? What color? Highlight_Damage = true Damage_Color = Color.new(128, 0, 0, 128) end end #============================================================================== # ** Module: Map_Tiles # Contains data and methods useful for working with maps and tiles #============================================================================== module Map_Tiles AUTOTILE_PARTS = [[18,17,14,13], [ 2,14,17,18], [13, 3,17,18], [ 2, 3,17,18], [13,14,17, 7], [ 2,14,17, 7], [13, 3,17, 7], [ 2, 3,17, 7], [13,14, 6,18], [ 2,14, 6,18], [13, 3, 6,18], [ 2, 3, 6,18], [13,14, 6, 7], [ 2,14, 6, 7], [13, 3, 6, 7], [ 2, 3, 6, 7], [16,17,12,13], [16, 3,12,13], [16,17,12, 7], [12, 3,16, 7], [10, 9,14,13], [10, 9,14, 7], [10, 9, 6,13], [10, 9, 6, 7], [18,19,14,15], [18,19, 6,15], [ 2,19,14,15], [ 2,19, 6,15], [18,17,22,21], [ 2,17,22,21], [18, 3,22,21], [ 2, 3,21,22], [16,19,12,15], [10, 9,22,21], [ 8, 9,12,13], [ 8, 9,12, 7], [10,11,14,15], [10,11, 6,15], [18,19,22,23], [ 2,19,22,23], [16,17,20,21], [16, 3,20,21], [ 8,11,12,15], [ 8, 9,20,21], [16,19,20,23], [10,11,22,23], [ 8,11,20,23], [ 0, 1, 4, 5]] WATERFALL_PIECES = [[ 2, 1, 6, 5], [ 0, 1, 4, 5], [ 2, 3, 6, 7], [0, 3, 4, 7]] WALL_PIECES = [[10, 9, 6, 5], [ 8, 9, 4, 5], [ 2, 1, 6, 5], [ 0, 1, 4, 5], [10,11, 6, 7], [ 8,11, 4, 7], [ 2, 3, 6, 7], [ 0, 3, 4, 7], [10, 9,14,13], [ 8, 9,12,13], [ 2, 1,14,13], [ 0, 1,12,13], [10,11,14,15], [8, 11,12,15], [ 2, 3,14,15], [ 0, 3,12,15]] A1_TILES = [[0, 0], [0, 96], [192, 0], [192, 96], [256, 0], [448, 0], [256, 96], [448, 96], [0, 192], [192, 192], [0, 288], [192, 288], [256, 192], [448, 192], [256, 288], [448, 288]] #-------------------------------------------------------------------------- # * Checks if a tile is a wall #-------------------------------------------------------------------------- def is_wall?(data) return true if data.between?(2288, 2335) return true if data.between?(2384, 2431) return true if data.between?(2480, 2527) return true if data.between?(2576, 2623) return true if data.between?(2672, 2719) return true if data.between?(2768, 2815) return true if data.between?(4736, 5119) return true if data.between?(5504, 5887) return true if data.between?(6272, 6655) return true if data.between?(7040, 7423) return true if data > 7807 false end #-------------------------------------------------------------------------- # * Checks if a tile is roof #-------------------------------------------------------------------------- def is_roof?(data) return true if data.between?(4352, 4735) return true if data.between?(5120, 5503) return true if data.between?(5888, 6271) return true if data.between?(6656, 7039) return true if data.between?(7424, 7807) false end #-------------------------------------------------------------------------- # * Checks if a tile is soil #-------------------------------------------------------------------------- def is_soil?(data) return true if data.between?(2816, 4351) && !is_table?(data) return true if data > 1663 && !is_stair?(data) false end #-------------------------------------------------------------------------- # * Checks if a tile is a stair #-------------------------------------------------------------------------- def is_stair?(data) return true if data.between?(1541, 1542) return true if data.between?(1549, 1550) return true if data.between?(1600, 1615) false end #-------------------------------------------------------------------------- # * Checks if a tile is a table #-------------------------------------------------------------------------- def is_table?(data) return true if data.between?(3152, 3199) return true if data.between?(3536, 3583) return true if data.between?(3920, 3967) return true if data.between?(4304, 4351) false end #-------------------------------------------------------------------------- # * The tileset to be used #-------------------------------------------------------------------------- def tileset $data_tilesets[@tileset_id] end #-------------------------------------------------------------------------- # * Region ID #-------------------------------------------------------------------------- def region_id(x, y) valid?(x, y) ? @map.data[x, y, 3] >> 8 : 0 end #-------------------------------------------------------------------------- # * Gets all of the tiles for each layer at position x,y #-------------------------------------------------------------------------- def layered_tiles(x, y) [2, 1, 0].collect {|z| @map.data[x, y, z] } end def layered_tiles_flag?(x, y, bit) layered_tiles(x, y).any? {|tile_id| tileset.flags[tile_id] & bit != 0 } end def valid?(x, y) x >= 0 && x < width && y >= 0 && y < height end def damage_floor?(x, y) valid?(x, y) && layered_tiles_flag?(x, y, 0x100) end #-------------------------------------------------------------------------- # * Specifies which type of autotile is used #-------------------------------------------------------------------------- def auto_tile(id) id / 48 end #-------------------------------------------------------------------------- # * Specifies the specific arrangement of autotiles used #-------------------------------------------------------------------------- def auto_index(id) id % 48 end #-------------------------------------------------------------------------- # * Put the auto-tile pieces together #-------------------------------------------------------------------------- def make_autotile(rects, sx, sy) @tile.clear for i in 0...4 @auto_rect.x = (rects[i] % 4) * 16 + sx @auto_rect.y = (rects[i] / 4) * 16 + sy @tile.blt((i % 2) * 16,(i / 2) * 16, @tilemap, @auto_rect) end end #-------------------------------------------------------------------------- # * Get auto-tile A1 tiles #-------------------------------------------------------------------------- def autotile_A1(tile_id) @tilemap = @bitmaps[0] autotile = tile_id / 48 auto_id = tile_id % 48 sx, sy = A1_TILES[autotile] if is_wall?(tile_id + 2048) rects = WATERFALL_PIECES[auto_id] else rects = AUTOTILE_PARTS[auto_id] end make_autotile(rects, sx, sy) end #-------------------------------------------------------------------------- # * Get auto-tile A2 tiles. # 64x96 tiles, 8 per row, 4 rows #-------------------------------------------------------------------------- def autotile_A2(tile_id) autotile = tile_id / 48 auto_id = tile_id % 48 @tilemap = @bitmaps[1] sx = (autotile % 8) * 64 sy = (autotile / 8 % 4) * 96 rects = AUTOTILE_PARTS[auto_id] make_autotile(rects, sx, sy) end #-------------------------------------------------------------------------- # * Get auto-tile A3 tiles. # 64x64 tiles, 8 per row, 4 rows #-------------------------------------------------------------------------- def autotile_A3(tid) @tilemap = @bitmaps[2] sx = (auto_tile(tid) % 8) * 64 sy = (auto_tile(tid) / 8 % 4) * 64 rects = WALL_PIECES[auto_index(tid)] make_autotile(rects, sx, sy) end #-------------------------------------------------------------------------- # * Get auto-tile A4 tiles (walls) #-------------------------------------------------------------------------- def autotile_A4(tile_id) @tilemap = @bitmaps[3] autotile = tile_id / 48 auto_id = tile_id % 48 sx = (autotile % 8) * 64 sy = (autotile / 16 * 160) + (autotile / 8 % 2) * 96 if is_wall?(tile_id + 5888) rects = WALL_PIECES[auto_id] else rects = AUTOTILE_PARTS[auto_id] end make_autotile(rects, sx, sy) end #-------------------------------------------------------------------------- # * Get auto-tile A5 tiles (normal) #-------------------------------------------------------------------------- def autotile_A5(tile_id) @tilemap = @bitmaps[4] sx = (tile_id) % 8 * tilesize sy = (tile_id) / 8 * tilesize @src_rect.set(sx, sy, tilesize, tilesize) @tile.clear @tile.blt(0, 0, @tilemap, @src_rect) end #-------------------------------------------------------------------------- # * Get normal tiles B, C, D, E #-------------------------------------------------------------------------- def normal_tile(tile_id) @tilemap = @bitmaps[5 + tile_id / 256] sx = (tile_id / 128 % 2 * 8 + tile_id % 8) * tilesize; sy = (tile_id % 256 / 8 % 16) * tilesize; @src_rect.set(sx, sy, tilesize, tilesize) @tile.clear @tile.blt(0, 0, @tilemap, @src_rect) end #-------------------------------------------------------------------------- # * Get bitmap for the specified tile id #-------------------------------------------------------------------------- def get_bitmap(id) if id < 1024 normal_tile(id) elsif id < 1664 autotile_A5(id - 1536) elsif id < 2816 autotile_A1(id - 2048) elsif id < 4352 autotile_A2(id - 2816) elsif id < 5888 autotile_A3(id - 4352) else autotile_A4(id - 5888) end end end #============================================================================== # ** #============================================================================== class Game_Player < Game_Character alias :th_mapsaver_update :update def update th_mapsaver_update if Input.trigger?(TH::Map_Saver::Mapshot_Button) s = Map_Saver.new($game_map.map_id) s.set_scale(TH::Map_Saver::Mapshot_Scale) s.mapshot end if Input.trigger?(TH::Map_Saver::Screenshot_Button) s = Map_Saver.new($game_map.map_id) s.set_scale(TH::Map_Saver::Screenshot_Scale) s.screenshot end end end class Game_Vehicle < Game_Character attr_reader :map_id end class Game_Map attr_reader :map end #============================================================================== # ** #============================================================================== class Map_Saver include TH::Map_Saver include Map_Tiles #-------------------------------------------------------------------------- # * Constants #-------------------------------------------------------------------------- SHADOW_COLOR = TH::Map_Saver::Shadow_Color DAMAGE_COLOR = TH::Map_Saver::Damage_Color #-------------------------------------------------------------------------- # * Public instance variables #-------------------------------------------------------------------------- attr_reader :map_image def initialize(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y) @scale = 1 @local_x = x @local_y = y @screen_local = false @shadow_bitmap = Bitmap.new(128, 128) @draw_layer0 = true @draw_layer1 = true @draw_layer2 = true @draw_events = Draw_Events @draw_vehicles = Draw_Vehicles @draw_player = Draw_Player @draw_followers = Draw_Followers @draw_shadow = Draw_Shadow @draw_damage = Highlight_Damage @draw_regions = Draw_Regions @draw_passages = Draw_Passages @tile = Bitmap.new(32, 32) #stores the current tile to be drawn @tilemap = nil @src_rect = Rect.new @auto_rect = Rect.new(0, 0, tilesize / 2, tilesize/ 2) #constant @tile_rect = Rect.new(0, 0, tilesize, tilesize) #constant end def load_tilesets bitmaps = [] tileset.tileset_names.each_with_index do |name, i| bitmaps[i] = Cache.tileset(name) end return bitmaps end #-------------------------------------------------------------------------- # * Refresh, possibly with a new map #-------------------------------------------------------------------------- def redraw(map_id=$game_map.map_id, x=$game_player.x, y=$game_player.y) @map_image.dispose if @map_image @map_id = map_id @local_x = x @local_y = y @game_map = Game_Map.new @game_map.setup(map_id) @map = @game_map.map @map_info = $data_mapinfos[map_id] @screen = $game_map.screen @tileset_id = @game_map.tileset.id @bitmaps = load_tilesets get_bounds @map_image = Bitmap.new(@width * tilesize, [url=home.php?mod=space&uid=291977]@height[/url] * tilesize) draw_map scale_map if @scale != 1 end #-------------------------------------------------------------------------- # * Pre-process. These will never change when drawing the map. #-------------------------------------------------------------------------- def get_bounds @start_x = start_x @start_y = start_y @end_x = end_x @end_y = end_y @width = width @height = height @tilesize = tilesize end def screen_tile_x Graphics.width / 32 end def screen_tile_y Graphics.height / 32 end #-------------------------------------------------------------------------- # * Sets the scale for the map #-------------------------------------------------------------------------- def set_scale(scale) @scale = scale end #-------------------------------------------------------------------------- # * Size of a tile #-------------------------------------------------------------------------- def tilesize 32 end #-------------------------------------------------------------------------- # * Width and height of the map, both locally and globally #-------------------------------------------------------------------------- def width end_x - @start_x end def height end_y - @start_y end #-------------------------------------------------------------------------- # * Starting and end positions, relative to the screen or map #-------------------------------------------------------------------------- def start_x @screen_local ? [[$game_player.x - screen_tile_x / 2, @map.width - screen_tile_x].min, 0].max : 0 end def start_y @screen_local ? [[$game_player.y - screen_tile_y / 2, @map.height - screen_tile_y].min, 0].max : 0 end def end_x @screen_local ? [[screen_tile_x, @local_x + screen_tile_x / 2 + 1].max, @map.width].min : @map.width end def end_y @screen_local ? [[screen_tile_y, @local_y + screen_tile_y / 2 + 1].max, @map.height].min : @map.height end #-------------------------------------------------------------------------- # * Draw tile onto image. x and y values are absolute coords. They should # be re-mapped based on the start_x and start_y values #-------------------------------------------------------------------------- def draw_tile(x, y, tile, rect) ox = (x - @start_x) * tilesize oy = (y - @start_y) * tilesize @map_image.blt(ox, oy, tile, rect) end #-------------------------------------------------------------------------- # * Get bitmap for the specified character #-------------------------------------------------------------------------- def get_character_bitmap(name) charmap = Cache.character(name) sign = name[/^[\!\$]./] if sign && sign.include?('$') cw = charmap.width / 3 ch = charmap.height / 4 else cw = charmap.width / 12 ch = charmap.height / 8 end return charmap, cw, ch end #-------------------------------------------------------------------------- # * Draw the character onto the tile #-------------------------------------------------------------------------- def set_character_bitmap(character, x, y) charmap, cw, ch = get_character_bitmap(character.character_name) index = character.character_index pattern = character.pattern < 3 ? character.pattern : 1 sx = (index % 4 * 3 + pattern) * cw sy = (index / 4 * 4 + (character.direction - 2) / 2) * ch @src_rect.set(sx, sy, cw, ch) x -= cw / (@tilesize * 2) if cw >= @tilesize y -= ch / (@tilesize * 2) if ch >= @tilesize draw_tile(x, y, charmap, @src_rect) end #-------------------------------------------------------------------------- # * create the shadow map #-------------------------------------------------------------------------- def make_shadow_map for s in 0 ... 16 x = s % 4 y = s / 4 if s & 0b1000 == 0b1000 @shadow_bitmap.fill_rect(x*tilesize+16, y*@tilesize+16, 16, 16, SHADOW_COLOR) end if s & 0b0100 == 0b0100 @shadow_bitmap.fill_rect(x*tilesize, y*@tilesize+16, 16, 16, SHADOW_COLOR) end if s & 0b0010 == 0b0010 @shadow_bitmap.fill_rect(x*tilesize+16, y*@tilesize, 16, 16, SHADOW_COLOR) end if s & 0b0001 == 0b0001 @shadow_bitmap.fill_rect(x*tilesize, y*@tilesize, 16, 16, SHADOW_COLOR) end end end def draw_parallax image = Cache.parallax(@map.parallax_name) @src_rect.set(0, 0, image.width, image.height) @map_image.blt(0, 0, image, @src_rect) end #-------------------------------------------------------------------------- # * Draw the shadow map #-------------------------------------------------------------------------- def draw_shadow_map for x in @start_x ... @end_x for y in @start_y ... @end_y _x, _y = x*@tilesize, y*@tilesize s = @map.data[x, y, 3] & 0b1111 if s != 0 x_ = (s % 4) * @tilesize y_ = (s / 4) * @tilesize @src_rect.set(x_, y_, @tilesize, @tilesize) draw_tile(x, y, @shadow_bitmap, @src_rect) end end end end #-------------------------------------------------------------------------- # * Draw the specified layer #-------------------------------------------------------------------------- def draw_layer(layer) for x in @start_x ... @end_x for y in @start_y ... @end_y _x, _y = x*@tilesize, y*@tilesize tile_id = @map.data[x, y, layer] next if tile_id == 0 get_bitmap(tile_id) draw_tile(x, y, @tile, @tile_rect) end end end #----------------------------------------------------------------------------- # Draw game regions #----------------------------------------------------------------------------- def draw_regions if $imported["TH_RegionOverlay"] image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@region_map).bitmap @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect, 255) end end def draw_passages if $imported["TH_OverlayPassageMap"] image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@passage_map).bitmap @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect, 255) end end #-------------------------------------------------------------------------- # * Draw the game player #-------------------------------------------------------------------------- def draw_player set_character_bitmap($game_player, $game_player.x, $game_player.y) if @map_id == $game_map.map_id end def draw_followers end #-------------------------------------------------------------------------- # * Draw map events #-------------------------------------------------------------------------- def draw_events @map.events.values.each do |event| id = event.pages[0].graphic.tile_id char_name = event.pages[0].graphic.character_name if id > 0 normal_tile(id) draw_tile(event.x, event.y, @tilemap, @src_rect) elsif char_name != "" set_character_bitmap(event.pages[0].graphic, event.x, event.y) end end end #-------------------------------------------------------------------------- # * Draw map vehicles #-------------------------------------------------------------------------- def draw_vehicles $game_map.vehicles.each do |vehicle| set_character_bitmap(vehicle, vehicle.x, vehicle.y,) if @map_id == vehicle.map_id end end #-------------------------------------------------------------------------- # * Draw map sprites #-------------------------------------------------------------------------- def draw_sprites draw_events if @draw_events draw_vehicles if @draw_vehicles draw_player if @draw_player draw_followers if @draw_followers end #-------------------------------------------------------------------------- # * Highlight damage tiles #-------------------------------------------------------------------------- def draw_damage @tile.clear @tile.fill_rect(0, 0, @tilesize, @tilesize, DAMAGE_COLOR) @src_rect.set(0, 0, @tilesize, @tilesize) for x in @start_x ... @end_x for y in @start_y ... @end_y _x, _y = x*@tilesize, y*@tilesize if damage_floor?(x, y) draw_tile(x, y, @tile, @src_rect) end end end end def draw_screen_effects end #-------------------------------------------------------------------------- # * Draw the map #-------------------------------------------------------------------------- def draw_map make_shadow_map if @draw_shadow draw_parallax draw_layer(0) draw_layer(1) draw_shadow_map draw_layer(2) draw_damage if @draw_damage draw_regions if @draw_regions draw_passages if @draw_passages draw_sprites draw_screen_effects end #-------------------------------------------------------------------------- # * Scale the map #-------------------------------------------------------------------------- def scale_map nw = @width * @scale nh = @height * @scale @src_rect.set(0, 0, @width, @height) scaled_map = Bitmap.new(nw, nh) scaled_rect = Rect.new(0, 0, nw, nh) scaled_map.stretch_blt(scaled_rect, @map_image, @src_rect) @map_image = scaled_map end #-------------------------------------------------------------------------- # * Take a mapshot of the map #-------------------------------------------------------------------------- def mapshot @screen_local = false redraw export(TH::Map_Saver::Mapshot_Directory) $game_message.add("Mapshot taken") end #-------------------------------------------------------------------------- # * Take a screenshot of the map #-------------------------------------------------------------------------- def screenshot @screen_local = true redraw export(TH::Map_Saver::Screenshot_Directory) $game_message.add("Screenshot taken") end #-------------------------------------------------------------------------- # * Get the format to export to #-------------------------------------------------------------------------- def get_format TH::Map_Saver::Export_Format end #-------------------------------------------------------------------------- # * Export the map to a file #-------------------------------------------------------------------------- def export(dirName="") format = get_format name = @map.display_name != "" ? @map.display_name : @map_info.name Dir.mkdir(dirName) unless File.directory?(dirName) filename = "%s\\%s.%s" %[dirName, name, format] t1 = Time.now @map_image.save(filename) t2 = Time.now $game_message.add("Exported in %f seconds" %[t2 - t1]) end end class Bitmap def save(filename, options = {}) options.merge!(format: File.extname(filename)[1..-1].to_sym) retval = false #bitmap = Gdiplus::Bitmap.new(:hbitmap, hbitmap) #bitmap = Gdiplus::Bitmap.new(:gdidib, *gdidib) # this seems to be the fastest one (RGSS 3.0.1, Windows 8 64-bit) bitmap = Gdiplus::Bitmap.new(:scan0, width, height, scan0) if bitmap retval = bitmap.save(:file, filename, options[:format]) bitmap.dispose end retval end private def _data_struct(offset = 0) @_data_struct ||= (DL::CPtr.new((object_id << 1) + 16).ptr + 8).ptr (@_data_struct + offset).ptr.to_i end def gdidib [_data_struct(8), _data_struct(16)] end def hbitmap _data_struct(44) end def scan0 _data_struct(12) end end # ★ GDI+ interface # ★★★★★★★★★★★★ # # Author : Cremno # module Gdiplus DLL = 'gdiplus.dll' def self.get_function name, import, export = 'L' Win32API.new DLL, name, import, export end FUNCTIONS = { GdiplusStartup: get_function('GdiplusStartup', 'PPP'), GdiplusShutdown: get_function('GdiplusShutdown', 'P', 'V'), GdipDisposeImage: get_function('GdipDisposeImage', 'P'), GdipSaveImageToFile: get_function('GdipSaveImageToFile', 'PPPP'), GdipCreateBitmapFromGdiDib: get_function('GdipCreateBitmapFromGdiDib', 'LLP'), GdipCreateBitmapFromHBITMAP: get_function('GdipCreateBitmapFromHBITMAP', 'LLP'), GdipCreateBitmapFromScan0: get_function('GdipCreateBitmapFromScan0', 'LLLLPP') } @@token = [0].pack('I') def self.token @@token end @@clsids = {} def self.clsids @@clsids end def self.gen_clsids return unless @@clsids.empty? func = Win32API.new('rpcrt4.dll', 'UuidFromString', 'PP', 'L') { bmp: '557cf400-1a04-11d3-9a73-0000f81ef32e', jpeg: '557cf401-1a04-11d3-9a73-0000f81ef32e', gif: '557cf402-1a04-11d3-9a73-0000f81ef32e', tiff: '557cf405-1a04-11d3-9a73-0000f81ef32e', png: '557cf406-1a04-11d3-9a73-0000f81ef32e' }.each_pair do |k, v| clsid = [0].pack('I') func.call(v, clsid) @@clsids[k] = clsid end @@clsids[:jpg] = @@clsids[:jpeg] @@clsids[:tif] = @@clsids[:tiff] end # TODO: prepend prefix (Gdip or Gdiplus) automatically def self.call(*args) name = args.shift func = FUNCTIONS[name] v = func.call(*args) if v && v != 0 msgbox "GDI+ error: #{v}\n\nFunction: #{name}\nArguments: #{args.inspect}" false else true end end def self.startup call :GdiplusStartup, @@token, [1, 0, 0, 0].pack('L4'), 0 end def self.shutdown call :GdiplusShutdown, @@token end class Image attr_reader :instance def initialize @instance = 0 true end def save(destination, *args) case destination when :file filename = args.shift << "\0" filename.encode!('UTF-16LE') argv = [:GdipSaveImageToFile, filename, Gdiplus.clsids[args.shift], 0] else raise ArgumentError, "unknown GDI+ image destination: #{source}" end argv.insert(1, @instance) Gdiplus.call *argv end def dispose Gdiplus.call :GdipDisposeImage, @instance end end class Bitmap < Image def initialize source, *args case source when :gdidib argv = [:GdipCreateBitmapFromGdiDib, args.shift, args.shift] when :hbitmap argv = [:GdipCreateBitmapFromHBITMAP, args.shift, 0] when :scan0 w = args.shift h = args.shift argv = [:GdipCreateBitmapFromScan0, w, h, w * -4, 0x26200a, args.shift] else raise ArgumentError, "unknown GDI+ bitmap source: #{source}" end argv.push([0].pack('I')) retval = Gdiplus.call *argv @instance = retval ? argv.last.unpack('I').first : 0 retval end end end if Gdiplus.startup Gdiplus.gen_clsids class << SceneManager alias_method :run_wo_gdip_shutdown, :run def run run_wo_gdip_shutdown Gdiplus.shutdown end end end #============================================================================== # * Compatibility add-ons #============================================================================== #Yami overlays if $imported["YSE-OverlayMapping"] class Map_Saver def draw_overlay_map_ground filename = YSA::OVERLAY::GROUND filename += $game_map.map_id.to_s filename += "-" + $game_variables[YSA::OVERLAY::GROUND_VARIABLE].to_s p filename image = Cache.overlay(filename) @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect) end def draw_overlay_map_parallax filename = YSA::OVERLAY::PARALLAX filename += $game_map.map_id.to_s filename += "-" + $game_variables[YSA::OVERLAY::PARALLAX_VARIABLE].to_s image = Cache.overlay(filename) @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect) end def draw_overlay_map_light filename = YSA::OVERLAY::LIGHT filename += $game_map.map_id.to_s filename += "-" + $game_variables[YSA::OVERLAY::LIGHT_VARIABLE].to_s image = Cache.overlay(filename) @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect, 10) end def draw_overlay_map_shadow filename = YSA::OVERLAY::SHADOW filename += $game_map.map_id.to_s filename += "-" + $game_variables[YSA::OVERLAY::SHADOW_VARIABLE].to_s image = Cache.overlay(filename) @src_rect.set(@start_x*tilesize, @start_y*tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect, 10) end alias :th_map_overlay_draw_map :draw_map def draw_map th_map_overlay_draw_map draw_overlay_map_ground if $game_switches[YSA::OVERLAY::GROUND_SWITCH] draw_overlay_map_parallax if $game_switches[YSA::OVERLAY::PARALLAX_SWITCH] draw_overlay_map_shadow if $game_switches[YSA::OVERLAY::SHADOW_SWITCH] draw_overlay_map_light if $game_switches[YSA::OVERLAY::LIGHT_SWITCH] end end end if $imported["TH_AreaOverlay"] class Map_Saver def draw_overlay_area_map image = SceneManager.scene.instance_variable_get(:@spriteset).instance_variable_get(:@area_map).bitmap @src_rect.set(@start_x * tilesize, @start_y * tilesize, image.width, image.height) @map_image.blt(0, 0, image, @src_rect, 255) end alias :th_area_overlay_draw_map :draw_map def draw_map th_area_overlay_draw_map draw_overlay_area_map end end end
欢迎光临 Project1 (https://rpg.blue/) | Powered by Discuz! X3.1 |