#============================================================================== # ** Drago - Core Engine # Version : 1.48 # Contact : littledrago.blogspot.com / forum.chaos-project.com #============================================================================== ($imported ||= {})[:drg_core_engine] = 1.48 # ============================================================================= # NOTE: # ----------------------------------------------------------------------------- # This is a devtool for me to make me easier for scripting # If you want to use this, put above all custom script & below Scene_Debug # # ============================================================================= # DOCUMENTATION: # ----------------------------------------------------------------------------- =begin Version History 1.42 - ▼ Fixed Graphics.fullscreen? 1.40 - ▼ Modified Game_Map#load_event 1.39 - ▼ Fixed glitch at Bitmap#draw_icon ▼ Added Fiber class ▼ Added Game_Map#load_event ▼ Added Game_Map#call_event 1.36 - ▼ Added Color class library 1.34 - ▼ Added Module#define_third_method(sym = nil, _alias = nil, prevent_stack = true, *a, &block) ▼ Added Bitmap#blur 1.31 - ▼ Added Module#attr_sec_reader(symbol, default=0) ▼ Added Module#attr_sec_accessor(symbol, *a, &block) ▼ Added Module#alias_sec_method(sym = nil, *a, &block) ▼ Added Module#define_sec_method(sym = nil, *a, &block) 1.29 - ▼ Added Array#have_all?(array) ▼ Added Array#have_any?(array) 1.27 - ▼ Added Added Graphics.brightness ▼ Added Graphics.wait(frames = 10) ▼ Added Graphics.fadein(frames = 10) ▼ Added Graphics.fadeout(frames = 10) ▼ Added Bitmap#invert ▼ Added Bitmap#invert! ▼ Added Bitmap#brighten(amount = 10) ▼ Added Bitmap#brighten!(amount = 10) ▼ Added Bitmap#darken(amount = 10) ▼ Added Bitmap#darken!(amount = 10) ▼ Added Bitmap#grayscale ▼ Added Bitmap#grayscale! ▼ Added Bitmap#pixelate(size = 10) ▼ Added Bitmap#pixelate!(size = 10) ▼ Added Bitmap#frost(noise = 10) ▼ Added Bitmap#frost!(noise = 10) 1.24 - ▼ Added Viewport#x ▼ Added Viewport#y ▼ Added Viewport#width ▼ Added Viewport#height ▼ Added Viewport#disposed? 1.23 - ▼ Added Window_Base#draw_text (same as Bitmap#draw_text) ▼ Added Window_Base#draw_icon ▼ Added Window_Base#draw_battler ▼ Added Window_Base#draw_picture 1.22 - ▼ Added Game_Map#load_map_data ▼ Added Game_Map#load_event ▼ Rename Array#product => Array#num_times (because of conflict with RGSS3) 1.21 - ▼ Fixed Glitch at Bitmap#crop 1.20 - ▼ Fixed Script Hanging Error at Bitmap#export 1.19 - ▼ Added some of RMXP old method - Game_System#play_bgm ▼ Added some of RMXP old method - Game_System#play_bgs ▼ Added some of RMXP old method - Game_System#play_me ▼ Added some of RMXP old method - Game_System#play_se 1.18 - ▼ Fixing Backtrace at Array#method_missing 1.17 - ▼ Added Bitmap#flip_vertical ▼ Added Bitmap#flip_vertical! ▼ Added Bitmap#flip_horizontal ▼ Added Bitmap#flip_horizontal! 1.16 - ▼ Added Bitmap#export 1.15 - ▼ Added Game_Characters#character_above? ▼ Added Game_Characters#character_below? ▼ Added Game_Characters#character_right? ▼ Added Game_Characters#character_left? 1.11 - ▼ Fixing Bug at changing screen size 1.10 - ▼ Added Graphics.scale_screen(width, height) 1.00 - ▼ Original Release # ----------------------------------------------------------------------------- # Below is the available command in this script # ----------------------------------------------------------------------------- # * Graphics # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- This command is not recommended to used in RMXP Graphics.scale_screen(width,height) - Resize the screen and stretched it (if not RMXP) into new resolution Graphics.fill_monitor - Maximize the screen and stretched it (if not RMXP) to fill the monitor Graphics.control_screen_size(enable = true) - Enable or disable screen size control by mouse. Resized screen will be stretched (if not RMXP) # ----------------------------------------------------------------------------- Graphics.width - Returns screen width Graphics.height - Returns screen height Graphics.fullscreen? - Returns true if Game in fullscreen mode, else false Graphics.fullscreen - Switch to fullscreen mode Graphics.window - Switch to windowed mode Graphics.toggle - Switch between fullscreen mode and windowed mode Graphics.wait(frame) - Wait for frame Graphics.wait_for_input - Wait until input is pressed Graphics.fadein(frame) - Fade in the screen Graphics.fadeout(frame) - Fade out the screen Graphics.snap_to_bitmap - Snap screen to a bitmap object Graphics.high_priority = true/false - Change process priority to high / normal Graphics.disable_alt_enter - Disable input ALT+Enter (until game is closed) # ----------------------------------------------------------------------------- # * Module # ----------------------------------------------------------------------------- Module#attr_sec_reader(symbol, default=0) - Create attr_reader with default value Example : attr_sec_reader :something, "Sprite.new" Equal : def something @something ||= Sprite.new end Module#attr_sec_accessor(symbol, *a, &block) - Create (sheer of) attr_accessor with default value Example : attr_sec_accessor :sprite1, :sprite2, :sprite3, "Sprite.new" Equal : attr_writer :sprite1, :sprite2, :sprite3 attr_sec_reader :sprite1, "Sprite.new" attr_sec_reader :sprite2, "Sprite.new" attr_sec_reader :sprite3, "Sprite.new" Module#alias_sec_method(sym = nil, *a, &block) - Create alias only if alias name is not defined and target method is exist Example : alias_sec_method :some_method, :target_method Equal : if method_defined?(:target) && !method_defined?(:something) alias_method :something, :target end Module#define_sec_method(sym = nil, *a, &block) - Define method only if the method is not defined Example : define_sec_method(:some_method) { |*a| block } Equal : unless method_defined?(:some_method) def some_method(*a) block end end # ----------------------------------------------------------------------------- # * Array # ----------------------------------------------------------------------------- Array Method Distributor - Distribute unexisted method in array into each variable (will work only if the method isn't exist in Array) Example : [Graphics,Input].update # equal => Graphics.update ; Input.update [@string1,@string2,@integer1,@sprite].dispose # equal => @sprite.dispose # (all variable without dispose method is ignored) [@string1,@string2,@integer1].dispose # Throws NoMethodError if all method didn't have dispose method Array#random_each / Array#random_each_with_index Example : a = [1,2,3,4,5,6,7] a.random_each {|i| puts i} # 4,5,3,2,7,1,6 Array#sum Array#num_times Array#average Example : [1,2,3,4].sum # 10 (1+2+3+4) [1,2,3,4].average # 2.5 (10 / 4) [1,2,3,4].num_times # 24 (1*2*3*4) Array#shuffle / Array#shuffle! Example : [1,2,3,4].shuffle # [3,2,4,1] Array#random / Array#random! Example : [1,2,3,4].random # 3 Array#switch=(true/false) Array#switch_reverse - Turn on / off switches all variable in the array (will ignored if variable not integer or not an array) Example : [1,2,[3,2,'A'],5].switch = true # equal => $game_switches[1] = true $game_switches[2] = true $game_self_switches[[3,2,'A']] = true $game_switches[5] = true Array#variable(value = nil, method = "=") - Change all variable value in the array (ignored if variable not integer) Example : [1,2,5].variable(10) # equal => $game_variables[1] = 10 $game_variables[2] = 10 $game_variables[5] = 10 Example : [1,2,5].variable(10, "+=") # equal => $game_variables[1] += 10 $game_variables[2] += 10 $game_variables[5] += 10 Array#have_all?(array) - returns true if contains all elements of the array Array#have_any?(array) - returns true if contains any elements of the array # ----------------------------------------------------------------------------- # * Sprite # ----------------------------------------------------------------------------- Sprite#clone Sprite#dup - Clone sprite without "can't clone sprite error" Example : a = Sprite.new b = a.clone a.dispose print a.disposed? # true print b.disposed? # false # ----------------------------------------------------------------------------- # * Spriteset_Map # ----------------------------------------------------------------------------- Spriteset_Map#sprite_player - returns sprite player at @character_sprites in Spriteset_Map Spriteset_Map#find_character(character) - returns character sprite at @character_sprites in Spriteset_Map # ----------------------------------------------------------------------------- # * Game Battler # ----------------------------------------------------------------------------- Game_Battler#hp_percent(integer = false, float_points = 2) Game_Battler#sp_percent(integer = false, float_points = 2) Example : $game_actors[1].hp_percent # returns 0 - 100 based on percentage hp # ----------------------------------------------------------------------------- # * Bitmap # ----------------------------------------------------------------------------- Bitmap#export(filename) - exporting bitmap into a file (only support bmp and png) Example : bitmap = Bitmap.new(50,20) bitmap.export('empty.png') Bitmap#flip_vertical Bitmap#flip_vertical! Bitmap#flip_horizontal Bitmap#flip_horizontal! - flip the bitmap vertically or horizontally (using ! will modify self) Example : bitmap = Bitmap.new(50,20) bitmap.flip_vertical! Additional Bitmap Effects Note : calling this method is process consuming, use with caution Bitmap#invert Bitmap#invert! Bitmap#brighten(amount = 10) Bitmap#brighten!(amount = 10) Bitmap#darken(amount = 10) Bitmap#darken!(amount = 10) Bitmap#grayscale Bitmap#grayscale! Bitmap#pixelate(size = 10) Bitmap#pixelate!(size = 10) Bitmap#frost(noise = 10) Bitmap#frost!(noise = 10) # ----------------------------------------------------------------------------- # * Color # ----------------------------------------------------------------------------- Color RGB value shortcut List : Color.red Color.white Color.black Color.green Color.blue Color.white Color.black Color.yellow Color.magenta Color.cyan Color.purple Color.gray Color.lightgray Color.darkgray Color.pink Color.orange Color.brown Color.golden Color Hex - You can use hex value as method in color class (not case sensitive) Example : Color.xffffff, Color.x04dacf, etc # ----------------------------------------------------------------------------- # * Game_Map # ----------------------------------------------------------------------------- Game_Map#load_event(mapid, eventid, x, y, page_id) Game_Map#load_event(mapid, eventid, x, y) Game_Map#load_event(eventid, x, y) # map_id will be assumed as current map - Duplicate an event from another map to current map at position (x, y) Game_Map#call_event(mapid, eventid, page_id) Game_Map#call_event(mapid, eventid) # page_id will be assumed as -1 Game_Map#call_event(eventid) # map_id will be assumed as current map - Call an event from another map to current map Note that page_id is start from 1, not 0 If you're using RMVX or RMVXA, setting page_id to -1 will bring you to the page with met condition. # ----------------------------------------------------------------------------- # * End Documentation # ----------------------------------------------------------------------------- =end # ============================================================================= module LiTTleDRAgo #------------------------------------------------------------------------- # * Constant #------------------------------------------------------------------------- VX = defined?(Window_ActorCommand) VXA = defined?(Window_BattleActor) XP = !VX RGSS1 = defined?(Hangup) RGSS2 = RUBY_VERSION == '1.8.1' && !RGSS1 RGSS3 = RUBY_VERSION == '1.9.2' APPPATHDRAGO = "#{ENV['APPDATA']}/Drago/" end #============================================================================== # ** Module #------------------------------------------------------------------------------ # #============================================================================== class Module #------------------------------------------------------------------------- # * New method: attr_sec_reader (Attr Secondary Reader) #------------------------------------------------------------------------- unless method_defined?(:attr_sec_reader) def attr_sec_reader(*sym) if (1..2) === sym.size module_eval("define_method(:#{sym[0]}) { @#{sym[0]} ||= #{sym[1]||0}}") elsif sym.size > 2 (default = sym.pop) && sym.each {|s| attr_sec_reader(s,default)} end end end #------------------------------------------------------------------------- # * New method: attr_sec_accessor (Attr Secondary Accessor) #------------------------------------------------------------------------- unless method_defined?(:attr_sec_accessor) def attr_sec_accessor(sym = nil, *args) (args.size > 0) | sym.nil? || args.push(0) (default = args.pop) && (b = [sym].concat(args).compact) (b).each {|a| (attr_writer(a) || 0) && attr_sec_reader(a,default)} end end #------------------------------------------------------------------------- # * New method: alias_sec_method (Alias Secondary Method) # Note : This method will create alias only if alias name is not defined # and target alias is exist #------------------------------------------------------------------------- unless method_defined?(:alias_sec_method) private def alias_sec_method(sym = nil, *args) (args.size > 0) | sym.nil? || args.clear (t = args.pop) && (b = [sym].concat(args).compact).each do |a| c = t == :initialize ? true : method_defined?(t) method_defined?(a) || (c && alias_method(a, t)) end end end #------------------------------------------------------------------------- # * New method: redirect_method #------------------------------------------------------------------------- unless method_defined?(:redirect_method) private def redirect_method(sym = nil, *args, &block) (args.size > 0) | sym.nil? || args.clear (t = args.pop) && (b = [sym].concat(args).compact).each do |a| meth = "def #{a}[*args] #{t}(*args) end" meth.gsub!(/(['")}\](\d+)])\(\*args\)/i) { $1 }#' meth.gsub!(/\[\*args\]/i) { '(*args)' } method_defined?(a) || module_eval(meth) end end end #------------------------------------------------------------------------- # * New method: define_sec_method # Note : This method will not defining method if method name already # exist #------------------------------------------------------------------------- unless method_defined?(:define_sec_method) private def define_sec_method(sym = nil, *args, &block) sym && (method_defined?(s = sym.to_sym) || define_method(s,*args,&block)) end private alias_method :define_inexist_method, :define_sec_method end #------------------------------------------------------------------------- # * New method: define_third_method # Note : After aliasing, define a method #------------------------------------------------------------------------- unless method_defined?(:define_third_method) private def define_third_method(sym = nil, _alias = nil, prevent_stack = true, *args, &block) unless sym.nil? || _alias.nil? stack = (prevent_stack && method_defined?(_alias.to_sym)) stack || alias_method(_alias.to_sym, sym.to_sym) define_method(sym.to_sym,*args,&block) end end private alias_method :define_after_alias_method, :define_third_method end end #============================================================================== # ** CoreDLL #------------------------------------------------------------------------------ # #============================================================================== module CoreDLL #------------------------------------------------------------------------- # * Constant #------------------------------------------------------------------------- DLL_USED = ['kernel32','msvcrt','user32','gdi32'] SCENEVXA = "SceneManager.send(:instance_variable_set,:@scene,args.at(0))" #------------------------------------------------------------------------- # * Public Instance Variables #------------------------------------------------------------------------- attr_sec_reader :rtlmemory_pi, "winapi(0,'RtlMoveMemory','pii','i')" attr_sec_reader :rtlmemory_ip, "winapi(0,'RtlMoveMemory','ipi','i')" attr_sec_reader :setpriority, "winapi(0,'SetPriorityClass','pi','i')" attr_sec_reader :getprocesstime,"winapi(0,'GetProcessTimes','ipppp','i')" attr_sec_reader :malloc, "winapi(1,'malloc','i','i')" attr_sec_reader :free, "winapi(1,'free','i','v')" attr_sec_reader :getdc, "winapi(2,'GetDC','i','i')" attr_sec_reader :releasedc, "winapi(2,'ReleaseDC','ii','i')" attr_sec_reader :reghotkey, "winapi(2,'RegisterHotKey', 'liii', 'i')" attr_sec_reader :sendinput, "winapi(2,'SendInput','ipi','i')" attr_sec_reader :setwindowlong, "winapi(2, 'SetWindowLong','lll','l')" attr_sec_reader :bitblt, "winapi(3,'BitBlt','iiiiiiiii','i')" attr_sec_reader :ccdc, "winapi(3,'CreateCompatibleDC','i','i')" attr_sec_reader :ccbitmap, "winapi(3,'CreateCompatibleBitmap','iii','i')" attr_sec_reader :deleteobject, "winapi(3,'DeleteObject','i','i')" attr_sec_reader :getbitmapbits, "winapi(3,'GetBitmapBits','llp','l')" attr_sec_reader :getdibits, "winapi(3,'GetDIBits','iiiiipi','i')" attr_sec_reader :setdibits, "winapi(3,'SetDIBits','iiiiipi','i')" attr_sec_reader :selectobject, "winapi(3,'SelectObject','ii','i')" attr_sec_reader :getpixel, "winapi(3,'GetPixel','iii','i')" attr_sec_reader :setpixel, "winapi(3,'SetPixel','liil','l')" attr_sec_reader :disabled_key, "Array.new" attr_sec_reader :high_priority, 'false' #------------------------------------------------------------------------- # * Define Secondary Listing #------------------------------------------------------------------------- define_sec_method(:disable_alt_enter) { disable_keys(0x0D) } define_sec_method(:fullscreen?) { systemmetrix.at(0) == Graphics.width } define_sec_method(:fullscreen) { toggle unless self.fullscreen? } define_sec_method(:window) { toggle if self.fullscreen? } #------------------------------------------------------------------------- # * Redirect Listing #------------------------------------------------------------------------- redirect_method :cache, LiTTleDRAgo::VX ? '(Cache)' : '(RPG::Cache)' redirect_method :scene, LiTTleDRAgo::VXA ? '(SceneManager.scene)':'($scene)' redirect_method :scene=,LiTTleDRAgo::VXA ? SCENEVXA : '($scene = args[0])' #------------------------------------------------------------------------- # * Enable change window size via mouse (border required) # Screen will not resized if RMXP #------------------------------------------------------------------------- def control_screen_size(enable = true) hid = @hide_border ? 0x14000000 : 0x14CA0000 set = enable ? (0x10C70000|0x00080000) : hid self.setwindowlong.call(self.hwnd,-16, set) end #------------------------------------------------------------------------- # * Hide window border # Screen size can't be controlled via mouse #------------------------------------------------------------------------- def hide_borders (@hide_border = true) && control_screen_size(false) end #------------------------------------------------------------------------- # * Show window border # Screen size can't be controlled via mouse #------------------------------------------------------------------------- def show_borders (@hide_border = false) || control_screen_size(false) end #------------------------------------------------------------------------- # * Disable Key #------------------------------------------------------------------------- def disable_keys(*keys) keys.each do |key| disabled_key.include?(key) || disabled_key.push(key) self.reghotkey.call(self.hwnd, 1, 0x0001, key) end end #------------------------------------------------------------------------- # * Resize the screen (scaled) # Screen will not resized if RMXP #------------------------------------------------------------------------- def scale_screen(width, height) res = self.systemmetrix width += (res.at(5) + res.at(45)) * 2 height += (res.at(6) + res.at(45)) * 2 + res.at(4) x = [(res.at(0) - width) / 2, 0].max y = [(res.at(1) - height) / 2, 0].max self.setwindowpos(self.hwnd,0,x,y,width,height,0) end #------------------------------------------------------------------------- # * Scale the game.exe to fill the monitor # Screen will not resized if RMXP #------------------------------------------------------------------------- def fill_monitor (res = systemmetrix) && setwindowpos(hwnd,0,0,0,res.at(0),res.at(1),0) end #------------------------------------------------------------------------- # * systemmetrix #------------------------------------------------------------------------- def systemmetrix @systemmetrix ||= winapi(2, 'GetSystemMetrics', %w(i), 'i') (res = []) && [0,1,4,5,6,45].each { |i| res[i] = @systemmetrix.call(i) } res end #------------------------------------------------------------------------- # * setwindowpos #------------------------------------------------------------------------- def setwindowpos(hwnd = self.hwnd,at = 0,x = 0,y = 0, width = 640, height = 480, ni = 0) @setwindowpos ||= winapi(2, 'SetWindowPos', 'liiiiip','i') @setwindowpos.call(hwnd, at, x, y, width, height, ni) end #------------------------------------------------------------------------- # * Toggle between fullscreen and windowed #------------------------------------------------------------------------- def toggle @keybd ||= winapi(2, 'keybd_event', %w(i i l l), 'v') [@keybd.call(0xA4, 0, 0, 0), @keybd.call(13, 0, 0, 0) ] [@keybd.call(13, 0, 2, 0), @keybd.call(0xA4, 0, 2, 0)] end #------------------------------------------------------------------------- # * Show FPS #------------------------------------------------------------------------- def show_fps @show_fps ||= winapi(2, 'keybd_event', %w(l l l l), '') @show_fps.call(0x71,0,0,0) sleep(0.1) @show_fps.call(0x71,0,2,0) end #------------------------------------------------------------------------- # * Get the Game Window's width and height #------------------------------------------------------------------------- def client_size rect = [0, 0, 0, 0].pack('l4') @window_c_rect ||= winapi(2, 'GetClientRect', %w(l p), 'i') @window_c_rect.call(self.hwnd, rect) right, bottom = rect.unpack('l4')[2..3] return right, bottom end #------------------------------------------------------------------------- # * Get the game window handle (specific to game) #------------------------------------------------------------------------- def hwnd @window_find ||= winapi(2, 'FindWindowEx', %w(l l p p), 'i') @game_window ||= @window_find.call(0,0,"RGSS Player",0) return @game_window end #------------------------------------------------------------------------- # * always_on_top (cannot be undone) #------------------------------------------------------------------------- def always_on_top res = self.systemmetrix width = Graphics.width + (res.at(5) + res.at(45)) * 2 height = Graphics.height + (res.at(6) + res.at(45)) * 2 + res.at(4) x = [(res.at(0) - width) / 2, 0].max y = [(res.at(1) - height) / 2, 0].max self.setwindowpos(self.hwnd,-1,x,y,width,height,0x0200) end #------------------------------------------------------------------------- # * Get the value of game.ini #------------------------------------------------------------------------- def read_ini(field, key, ini = 'Game.ini') @gpps ||= winapi(0, 'GetPrivateProfileString', 'pppplp', 'l') @gpps.call(field,key,"",result="\0"*256,256,".//#{ini}") rescue return "" return result.delete!("\0") end #------------------------------------------------------------------------- # * High Priority (true/false) #------------------------------------------------------------------------- def high_priority=(value) @high_priority = value && true setpriority.call(-1, @high_priority ? 0x00000080 : 0x00000020) end #-------------------------------------------------------------------------- # * snap_to_bitmap #-------------------------------------------------------------------------- def snap_to_bitmap width, height = client_size.at(0), client_size.at(1) bitmap = Bitmap.new(width, height) dc = getdc.call(hwnd) address = bitmap.address info = [40,width,height,1,32,0,0,0,0,0,0].pack('LllSSLLllLL') hDC = ccdc.call(dc) hBM = ccbitmap.call(dc, width, height) deleteobject.call(selectobject.call(hDC, hBM)) setdibits.call(hDC, hBM, 0, height, address, info, 0) bitblt.call(hDC, 0, 0, width, height, dc, 0, 0, 0xCC0020) getdibits.call(hDC, hBM, 0, height, address, info, 0) deleteobject.call(hBM) deleteobject.call(hDC) bitmap end #------------------------------------------------------------------------- # * Execute Win32API #------------------------------------------------------------------------- def winapi(*args) args[0] = (i = args.at(0)).is_a?(Integer) ? DLL_USED[i] : i Win32API.new(*args) end end LiTTleDRAgo.extend(CoreDLL) #============================================================================== # ** RPG #------------------------------------------------------------------------------ # #============================================================================== module RPG #-------------------------------------------------------------------------- # ● Constant #-------------------------------------------------------------------------- VX, VXA = LiTTleDRAgo::VX, LiTTleDRAgo::VXA #============================================================================ # ** System #---------------------------------------------------------------------------- # #============================================================================ class System #======================================================================== # ** Words #------------------------------------------------------------------------ # #======================================================================== class Words #---------------------------------------------------------------------- # ● New Methods #---------------------------------------------------------------------- attr_sec_accessor :weapon1, VX && !VXA ? 'Vocab.weapon1' : "'Weapon 1'" attr_sec_accessor :weapon2, VX && !VXA ? 'Vocab.weapon2' : "'Weapon 2'" attr_sec_accessor :status, VX ? 'Vocab.status' : "'Status' " attr_sec_accessor :save, VX ? 'Vocab.save' : "'Save' " attr_sec_accessor :game_end, VX ? 'Vocab.game_end' : "'Game End'" attr_sec_accessor :fight, VX ? 'Vocab.fight' : "'Fight' " attr_sec_accessor :escape, VX ? 'Vocab.escape' : "'Escape' " attr_sec_accessor :new_game, VX ? 'Vocab.new_game' : "'New Game'" attr_sec_accessor :continue, VX ? 'Vocab.continue' : "'Continue'" attr_sec_accessor :shutdown, VX ? 'Vocab.shutdown' : "'Shutdown'" attr_sec_accessor :to_title, VX ? 'Vocab.to_title' : "'To Title'" attr_sec_accessor :cancel, VX ? 'Vocab.cancel' : "'Cancel' " attr_sec_accessor :params, !VXA ? !VX ? '[hp,sp,str,dex,agi,int]' : # XP '[hp,sp,atk,pdef,int,agi]' : # VX '[hp,sp,atk,pdef,int,mdef,agi,luk]' # VXA #---------------------------------------------------------------------- # ● Redirect Listings #---------------------------------------------------------------------- redirect_method :gold, (VXA ? 'Vocab.currency_unit' : 'Vocab.gold') redirect_method :hp, 'Vocab.hp' redirect_method :sp, 'Vocab.mp' redirect_method :str, 'String.new()' redirect_method :dex, 'String.new()' redirect_method :luk, (VXA ? 'Vocab.param(7)' : 'String.new()') redirect_method :agi, (VXA ? 'Vocab.param(6)' : 'Vocab.agi') redirect_method :int, (VXA ? 'Vocab.param(4)' : 'Vocab.spi') redirect_method :atk, (VXA ? 'Vocab.param(2)' : 'Vocab.atk') redirect_method :pdef, (VXA ? 'Vocab.param(3)' : 'Vocab.def') redirect_method :mdef, (VXA ? 'Vocab.param(5)' : 'String.new()') redirect_method :weapon, (VXA ? 'Vocab.etype(0)' : 'Vocab.weapon') redirect_method :armor1, (VXA ? 'Vocab.etype(1)' : 'Vocab.armor1') redirect_method :armor2, (VXA ? 'Vocab.etype(2)' : 'Vocab.armor2') redirect_method :armor3, (VXA ? 'Vocab.etype(3)' : 'Vocab.armor3') redirect_method :armor4, (VXA ? 'Vocab.etype(4)' : 'Vocab.armor4') redirect_method :attack, 'Vocab.attack' redirect_method :skill, 'Vocab.skill' redirect_method :guard, 'Vocab.guard' redirect_method :item, 'Vocab.item' redirect_method :equip, 'Vocab.equip' end #---------------------------------------------------------------------- # ● Class Variables #---------------------------------------------------------------------- if VX #------------------------------------------------------------------------ # ● Public Instance Variables #------------------------------------------------------------------------ attr_accessor :magic_number, :windowskin_name, :gameover_name attr_accessor :battle_transition, :battleback_name, :title_name #------------------------------------------------------------------------ # ● Redefined Methods #------------------------------------------------------------------------ redirect_method :sounds, "$data_system.sounds" redirect_method :cursor_se, "sounds[0]" redirect_method :decision_se, "sounds[1]" redirect_method :cancel_se, "sounds[2]" redirect_method :buzzer_se, "sounds[3]" redirect_method :equip_se, "sounds[4]" redirect_method :save_se, "sounds[5]" redirect_method :load_se, "sounds[6]" redirect_method :battle_start_se, "sounds[7]" redirect_method :escape_se, "sounds[8]" redirect_method :shop_se, "sounds[#{VXA} ? 21 : 17]" redirect_method :actor_collapse_se, "sounds[#{VXA} ? 15 : 13]" redirect_method :enemy_collapse_se, "sounds[11]" redirect_method :words, "@words ||= RPG::System::Words.new()" #------------------------------------------------------------------------ # ● Aliased Methods #------------------------------------------------------------------------ alias_sec_method :battleback_name, :battleback1_name alias_sec_method :title_name, :title1_name end end end #============================================================================== # ** Sound #------------------------------------------------------------------------------ # This module plays sound effects. It obtains sound effects specified in the # database from the global variable $data_system, and plays them. #============================================================================== module Sound #------------------------------------------------------------------------- # * Self #------------------------------------------------------------------------- class << self #------------------------------------------------------------------------ # ● New Method :se_play #------------------------------------------------------------------------ unless method_defined?(:se_play) def se_play(type) system = ($game_system ||= Game_System.new) case type when :cursor then system.se_play($data_system.cursor_se) when :decision then system.se_play($data_system.decision_se) when :cancel then system.se_play($data_system.cancel_se) when :buzzer then system.se_play($data_system.buzzer_se) when :shop then system.se_play($data_system.shop_se) when :equip then system.se_play($data_system.equip_se) when :save then system.se_play($data_system.save_se) when :load then system.se_play($data_system.load_se) when :battle_start then system.se_play($data_system.battle_start_se) when :escape then system.se_play($data_system.escape_se) when :actor_collapse then system.se_play($data_system.actor_collapse_se) when :enemy_collapse then system.se_play($data_system.enemy_collapse_se) end end end #-------------------------------------------------------------------------- # * Redefined Method #-------------------------------------------------------------------------- define_sec_method(:play_cursor) { se_play(:cursor) } define_sec_method(:play_decision) { se_play(:decision) } define_sec_method(:play_cancel) { se_play(:cancel) } define_sec_method(:play_buzzer) { se_play(:buzzer) } define_sec_method(:play_equip) { se_play(:equip) } define_sec_method(:play_save) { se_play(:save) } define_sec_method(:play_load) { se_play(:load) } define_sec_method(:play_battle_start) { se_play(:battle_start) } define_sec_method(:play_escape) { se_play(:escape) } define_sec_method(:play_enemy_collapse) { se_play(:enemy_collapse) } define_sec_method(:play_actor_collapse) { se_play(:actor_collapse) } define_sec_method(:play_shop) { se_play(:shop) } #-------------------------------------------------------------------------- # * Alias Listing #-------------------------------------------------------------------------- alias_sec_method :play_ok, :play_decision end end #============================================================================== # ** Game_System #------------------------------------------------------------------------------ # This class handles data surrounding the system. Backround music, etc. # is managed here as well. Refer to "$game_system" for the instance of # this class. #============================================================================== class Game_System #-------------------------------------------------------------------------- # * Constant #-------------------------------------------------------------------------- USE_VOLUME_SOUND = false VX = LiTTleDRAgo::VX && !LiTTleDRAgo::VXA #-------------------------------------------------------------------------- # * Public Instance Variable #-------------------------------------------------------------------------- attr_sec_accessor :bgm_volume, :bgs_volume, :me_volume, :se_volume, 100 attr_sec_accessor :bgm_pitch, :bgs_pitch, :me_pitch, :se_pitch , 100 #-------------------------------------------------------------------------- # * Redefined method: bgm_play, bgs_play, me_play, se_play, playing_bgm # bgm_memorize, bgm_restore #-------------------------------------------------------------------------- rewrite = method_defined?(:bgm_play) && !USE_VOLUME_SOUND rewrite || define_method(:bgm_play){ |*a| drg_bgm_play(*a) } rewrite || define_method(:bgs_play){ |*a| drg_bgs_play(*a) } rewrite || define_method(:me_play) { |*a| drg_me_play(*a) } rewrite || define_method(:se_play) { |*a| drg_se_play(*a) } VX && define_sec_method(:bgm_memorize) { @memorized_bgm = @playing_bgm } VX && define_sec_method(:bgm_restore) { bgm_play(@memorized_bgm) } #-------------------------------------------------------------------------- # * Redirect Listing #-------------------------------------------------------------------------- redirect_method :bgm_stop, 'Audio.bgm_stop' redirect_method :bgs_stop, 'Audio.bgs_stop' redirect_method :se_stop, 'Audio.se_stop' #-------------------------------------------------------------------------- # * Alias Listing #-------------------------------------------------------------------------- alias_sec_method :bgm_memorize, :save_bgm alias_sec_method :bgm_restore, :replay_bgm alias_sec_method :save_bgm, :bgm_memorize alias_sec_method :replay_bgm, :bgm_restore #-------------------------------------------------------------------------- # * New method: drg_bgm_play #-------------------------------------------------------------------------- unless method_defined?(:drg_bgm_play) def drg_bgm_play(bgm,*_a) @playing_bgm = bgm if bgm.is_a?(RPG::AudioFile) and bgm.name != "" a = ["Audio/BGM/" + bgm.name, bgm.volume * bgm_volume.to_f / 100, bgm.pitch * bgm_pitch.to_f / 100] a << _a.at(0) if _a.at(0) && LiTTleDRAgo::RGSS3 Audio.bgm_play(*a) elsif bgm.is_a?(String) && bgm != '' a = ["Audio/BGM/" + bgm, bgm_volume, bgm_pitch] a << _a.at(0) if _a.at(0) && LiTTleDRAgo::RGSS3 Audio.bgm_play(*a) else Audio.bgm_stop end Graphics.frame_reset end end #-------------------------------------------------------------------------- # * New method: drg_bgs_play #-------------------------------------------------------------------------- unless method_defined?(:drg_bgs_play) def drg_bgs_play(bgs,*_a) @playing_bgs = bgs if bgs.is_a?(RPG::AudioFile) and bgs.name != "" a = ["Audio/BGS/" + bgs.name, bgs.volume * bgs_volume.to_f / 100, bgs.pitch * bgs_pitch.to_f / 100] a << _a.at(0) if _a.at(0) && LiTTleDRAgo::RGSS3 Audio.bgs_play(*a) elsif bgs.is_a?(String) && bgs != '' a = ["Audio/BGS/" + bgs, bgs_volume, bgs_pitch] a << _a.at(0) if _a.at(0) && LiTTleDRAgo::RGSS3 Audio.bgs_play(*a) else Audio.bgs_stop end Graphics.frame_reset end end #-------------------------------------------------------------------------- # * New method: drg_me_play #-------------------------------------------------------------------------- unless method_defined?(:drg_me_play) def drg_me_play(me,*_a) if me.is_a?(RPG::AudioFile) and me.name != "" a = ["Audio/ME/" + me.name, me.volume * me_volume.to_f / 100, me.pitch * me_pitch.to_f / 100] Audio.me_play(*a) elsif me.is_a?(String) && me != '' a = ["Audio/ME/" + me, me_volume, me_pitch] Audio.me_play(*a) else Audio.me_stop end Graphics.frame_reset end end #-------------------------------------------------------------------------- # * New method: drg_se_play #-------------------------------------------------------------------------- unless method_defined?(:drg_se_play) def drg_se_play(se,*_a) if se.is_a?(RPG::AudioFile) and se.name != "" a = ["Audio/SE/" + se.name, se.volume * se_volume.to_f / 100, se.pitch * se_pitch.to_f / 100] Audio.se_play(*a) elsif se.is_a?(String) && se != '' a = ["Audio/SE/" + se, se_volume, se_pitch] Audio.se_play(*a) end end end end #============================================================================== # ** Object #------------------------------------------------------------------------------ # This class is superclass for all class #============================================================================== class Object #------------------------------------------------------------------------- # * New method: all_variable_dispose #------------------------------------------------------------------------- def all_variable_dispose all = instance_variables.map {|s| instance_variable_get("#{s}")}.flatten all.delete_if {|s| s.not.respond_to?(:dispose) } all.delete_if {|s| s.respond_to?(:disposed?) && s.disposed?} all.dispose end #------------------------------------------------------------------------- # * New method: rand_between #------------------------------------------------------------------------- unless method_defined?(:rand_between) def rand_between(min, max) min + rand(max - min + 1) if min.is_a?(Numeric) && max.is_a?(Numeric) end end #------------------------------------------------------------------------- # * New method: get_note #------------------------------------------------------------------------- unless method_defined?(:get_note) def get_note respond_to?(:note) ? note : "" end end #------------------------------------------------------------------------- # * New method: screen_rect #------------------------------------------------------------------------- unless method_defined?(:screen_rect) def screen_rect(as_rect = true) array = [0,0,Graphics.width,Graphics.height] as_rect ? Rect.new(*array) : array end end #------------------------------------------------------------------------- # * New method: force_save #------------------------------------------------------------------------- unless method_defined?(:force_save) def force_save(index) return DataManager.save_game(index) if defined?(DataManager) save = LiTTleDRAgo::VX ? Scene_File.new(0,nil,0) : Scene_Save.new begin file = File.open(save.make_filename(index), "wb") (save.write_save_data(file) && file.close) || true rescue File.delete(save.make_filename(index)) rescue nil (Sound.play_buzzer) && false end end alias_method :forcesave, :force_save end #-------------------------------------------------------------------------- # * sprite_report #-------------------------------------------------------------------------- unless method_defined?(:script_report) def script_report(text,font = nil) (s = Sprite.new) (s.opacity = 0) && s.bitmap = Bitmap.new((g = Graphics).width,g.height) (s.bitmap.font.name = ['Georgia',Font.default_name].flatten) (s.bitmap.font = (font || s.bitmap.font)) (s.bitmap.draw_enter_text(0,0,g.width,g.height,text,1)) (s.opacity += 10) && g.update until s.opacity >= 255 (g.wait_for_input) (s.opacity -= 10) && g.update until s.opacity <= 0 (s.dispose) end end #------------------------------------------------------------------------- # * New method: not #------------------------------------------------------------------------- define_sec_method(:not) { Not.new(self) } #============================================================================ # ** Not #---------------------------------------------------------------------------- # #============================================================================ class Not #------------------------------------------------------------------------- # * Private #------------------------------------------------------------------------- private *instance_methods.select { |m| m !~ /(^__|^\W|^binding$)/ } #------------------------------------------------------------------------- # * Object Initialization #------------------------------------------------------------------------- def initialize(original) @original = original end #------------------------------------------------------------------------- # * New method: method_missing #------------------------------------------------------------------------- def method_missing(sym, *a, &blk) !@original.send(sym, *a, &blk) end end end #============================================================================== # ** Kernel #------------------------------------------------------------------------------ # #============================================================================== module Kernel #------------------------------------------------------------------------- # * Alias Listing #------------------------------------------------------------------------- $@ || alias_method(:carrot, :proc) #------------------------------------------------------------------------- # * Script Check #------------------------------------------------------------------------- if LiTTleDRAgo::XP && LiTTleDRAgo::RGSS3 $@ || alias_method(:last_before_p, :p) $@ || alias_method(:last_before_print, :print) $@ || alias_method(:last_before_msgbox, :msgbox) $@ || alias_method(:last_before_msgbox_p, :msgbox_p) define_method(:p) {|*args| last_before_msgbox_p(*args)} define_method(:print) {|*args| last_before_msgbox(*args) } define_method(:msgbox) {|*args| last_before_print(*args) } define_method(:msgbox_p){|*args| last_before_p(*args) } end #------------------------------------------------------------------------- # * New method: press_any_key #------------------------------------------------------------------------- unless method_defined?(:press_any_key) def press_any_key return false if Input.nil? return true if Input.trigger?(Input::A) ||Input.trigger?(Input::B) return true if Input.trigger?(Input::C) ||Input.trigger?(Input::X) return true if Input.trigger?(Input::Y) ||Input.trigger?(Input::Z) return true if Input.trigger?(Input::L) ||Input.trigger?(Input::R) return true if Input.trigger?(Input::UP) ||Input.trigger?(Input::DOWN) return true if Input.trigger?(Input::LEFT) ||Input.trigger?(Input::RIGHT) return true if Input.trigger?(Input::SHIFT)||Input.trigger?(Input::CTRL) return true if Input.trigger?(Input::ALT) ||Input.trigger?(Input::F5) return true if Input.trigger?(Input::F6) ||Input.trigger?(Input::F7) return true if Input.trigger?(Input::F8) ||Input.trigger?(Input::F9) end end #------------------------------------------------------------------------- # * New method: inspect_instance_variable #------------------------------------------------------------------------- unless method_defined?(:inspect_instance_variable) def inspect_instance_variable(class_name, variable) Module.const_get(class_name).new.instance_variable_get(:"@#{variable}") end end end #============================================================================== # ** Proc #------------------------------------------------------------------------------ # #============================================================================== class Proc #------------------------------------------------------------------------- # * New method: bind #------------------------------------------------------------------------- unless method_defined?(:bind) def bind(object) block, time = self, Time.now class << object self end.class_eval do method_name = "__bind_#{time.to_i}_#{time.usec}" define_method(method_name, &block) method = instance_method(method_name) remove_method(method_name) method end.bind(object) end end end #============================================================================== # ** Enumerable #------------------------------------------------------------------------------ # #============================================================================== module Enumerable #--------------------------------------------------------------------------- # * Redefined method: shuffle #--------------------------------------------------------------------------- define_sec_method(:shuffle) {(a = entries) && Array.new(size){ a.random!}} #--------------------------------------------------------------------------- # * New method: random_each #--------------------------------------------------------------------------- unless method_defined?(:random_each) def random_each() (block_given? ? shuffle.each {|s| yield s } : random) end end #--------------------------------------------------------------------------- # * New method: random_each_with_index #--------------------------------------------------------------------------- unless method_defined?(:random_each_with_index) def random_each_with_index if block_given? self.shuffle.each_with_index { |obj, i| yield obj, i } else self.random end end end #--------------------------------------------------------------------------- # * Redefined method: drop_while #--------------------------------------------------------------------------- unless method_defined?(:drop_while) def drop_while(&block) ary, state = [], false self.each do |e| state = true if !state and !block.call(e) ary << e if state end ary end end #--------------------------------------------------------------------------- # * Redefined method: take_while #--------------------------------------------------------------------------- unless method_defined?(:take_while) def take_while(&block) ary = [] self.each do |e| return ary unless block.call(e) ary << e end ary end end #--------------------------------------------------------------------------- # * Redefined method: partition #--------------------------------------------------------------------------- unless method_defined?(:partition) def partition(&block) ary_T, ary_F = [], [] self.each {|val| block.call(val) ? ary_T.push(val) : ary_F.push(val)} return ary_T, ary_F end end #--------------------------------------------------------------------------- # * Redefined method: grep #--------------------------------------------------------------------------- unless method_defined?(:grep) def grep(pattern, &block) collect {|v| pattern === v && ary.push((block)? block.call(v): v)} end end #--------------------------------------------------------------------------- # * Redefined method: each_slice #--------------------------------------------------------------------------- unless method_defined?(:each_slice) def each_slice(n, &block) n.is_a?(Integer) || raise(TypeError,"expected Integer for 1st argument") n <= 0 && raise(ArgumentError, "invalid slice size") ary = [] self.each do |e| ary << e if ary.size == n block.call(ary) ary = [] end end block.call(ary) unless ary.empty? end end #--------------------------------------------------------------------------- # * Redefined method: minmax #--------------------------------------------------------------------------- unless method_defined?(:minmax) def minmax(&block) (a = sort(&block)) && [a.first,a.last] end end end #============================================================================== # ** Array #------------------------------------------------------------------------------ # #============================================================================== class Array #--------------------------------------------------------------------------- # * Define Secondary Listing #--------------------------------------------------------------------------- define_sec_method(:switch_on) { self.switch = true } define_sec_method(:switch_off) { self.switch = false } define_sec_method(:random) { self.at(rand(size)) } define_sec_method(:random!) { self.delete_at(rand(size)) } define_sec_method(:have_all?) { |*array| self & array == array } define_sec_method(:have_any?) { |*array| self - array != self } define_sec_method(:sum) { self.inject(0) {|r, n| r += n} } define_sec_method(:num_times) { self.inject(1) {|r, n| r *= n} } define_sec_method(:relay) { |type| map {|s| s.send(:"to_#{type}")}} define_sec_method(:next_item) { (item = shift) && push(item) && item } define_sec_method(:previous_item) { (item = pop) && unshift(item) && item } #--------------------------------------------------------------------------- # * New method: method_missing #--------------------------------------------------------------------------- def method_missing(val,*a,&b) en = self.entries.find_all {|s|s.respond_to?(val.to_sym)} if self.not.empty? && en.empty? text = "Undefined method #{val} at #{self.inspect}" raise(NoMethodError,text,caller(1)) end return en.map {|s| s.send(val.to_s,*a,&b)} end #------------------------------------------------------------------------- # * New method: each_ntuple #------------------------------------------------------------------------- unless method_defined?(:each_ntuple) def each_ntuple(number) 0.step(size - size % number - 1, number) {|i| yield(*self[i, number])} end end #------------------------------------------------------------------------- # * New method: each_pair #------------------------------------------------------------------------- unless method_defined?(:each_pair) def each_pair() each_ntuple(2) {|a,b| yield a, b } end end #--------------------------------------------------------------------------- # * New method: each_triple #--------------------------------------------------------------------------- unless method_defined?(:each_triple) def each_triple() each_ntuple(3) {|a,b,c| yield a, b, c } end end #--------------------------------------------------------------------------- # * Redefined method: shuffle! (for RMXP) #--------------------------------------------------------------------------- unless method_defined?(:shuffle!) def shuffle! self.dup == replace(shuffle) ? nil : self end end #--------------------------------------------------------------------------- # * New method: sort_by! #--------------------------------------------------------------------------- unless method_defined?(:sort_by!) def sort_by!(*args,&block) self.dup == replace(sort_by(*args,&block)) ? nil : self end end #--------------------------------------------------------------------------- # * New method: recursive_clone #--------------------------------------------------------------------------- unless method_defined?(:rclone) def recursive_clone clon = self.clone clon.each_index do |i| clon[i] = clon[i].recursive_clone rescue clon[i].clone rescue clon[i] end clon end alias_method(:rclone, :recursive_clone) end #--------------------------------------------------------------------------- # * New method: to_hash #--------------------------------------------------------------------------- unless method_defined?(:to_hash) def to_hash (hash = Hash.new) && each_index {|i| hash[i] = self[i]} && hash end end #--------------------------------------------------------------------------- # * New method: each_with_next #--------------------------------------------------------------------------- unless method_defined?(:each_with_next) def each_with_next(num = 1) (size - num).times {|i| yield(*self[i..(i+num)])} end end #--------------------------------------------------------------------------- # * New method: switch= #--------------------------------------------------------------------------- unless method_defined?(:switch=) def switch=(value) integer = search_var_key[0] array = search_var_key[1] if value == :flip integer.each {|i| $game_switches[i] = !$game_switches[i] } array.each {|i| $game_self_switches[i] = !$game_self_switches[i] } else integer.each {|i| $game_switches[i] = value } array.each {|i| $game_self_switches[i] = value } end $game_map.need_refresh = true if $game_map.respond_to?(:need_refresh) end end #--------------------------------------------------------------------------- # * New method: switch_reverse #--------------------------------------------------------------------------- def switch_reverse switch=(:flip) end #--------------------------------------------------------------------------- # * New method: variable #--------------------------------------------------------------------------- def variable(value = nil,method = "=") integer = search_var_key[0] integer += search_var_key[1] if $drago_game_variable return integer.map {|i| $game_variables[i]} if value.nil? result = integer.map {|i| eval("$game_variables[i] #{method} #{value}") } $game_map.need_refresh = true if $game_map.respond_to?(:need_refresh) result end #--------------------------------------------------------------------------- # * New method: search_var_key #--------------------------------------------------------------------------- def search_var_key integer = self.find_all {|s| s.is_a?(Integer)} range = self.find_all {|s| s.is_a?(Range) } array = self.find_all {|s| s.is_a?(Array) } string = self.find_all {|s| s.is_a?(String) } integer = integer + range.collect {|s| s.to_a }.flatten $game_switches ||= Game_Switches.new $game_self_switches ||= Game_SelfSwitches.new $game_variables ||= Game_Variables.new return [integer.sort.uniq, array.sort.uniq] end #--------------------------------------------------------------------------- # * New method: rindexes #--------------------------------------------------------------------------- unless method_defined?(:rindexes) def rindexes(*values) array = Array.new each_index {|i| values.include?(self[i]) && array.push(i)} array end end #--------------------------------------------------------------------------- # * New method: deep #--------------------------------------------------------------------------- unless method_defined?(:deep) def deep(deep = -1) tmp_deep = deep + 1 deep = tmp_deep self.each do |i| deep < i.deep(tmp_deep) && deep = i.deep(tmp_deep) rescue nil end deep end end #--------------------------------------------------------------------------- # * New method: recursive_flatten #--------------------------------------------------------------------------- unless method_defined?(:rflatten) def recursive_flatten array = self.recursive_clone array.each_index do |i| array[i] = array[i].to_a if array[i].is_a?(Hash) array[i] = array[i].recursive_flatten rescue array[i] end array.flatten! array end alias_method(:rflatten, :recursive_flatten) end #--------------------------------------------------------------------------- # * New method: recursive_flatten! #--------------------------------------------------------------------------- unless method_defined?(:rflatten!) def recursive_flatten! self.each_index do |i| self[i] = self[i].to_a if self[i].is_a?(Hash) self[i] = self[i].recursive_flatten! rescue self[i] end self.flatten! self end alias_method(:rflatten!, :recursive_flatten!) end #--------------------------------------------------------------------------- # * New method: insert2 #--------------------------------------------------------------------------- def insert2(i, obj) if i == 0 obj + self elsif i == self.size self + obj elsif self.size < i self + Array.new(i - self.size) + obj else self[0, i - 1] + obj + self[i, self.size] end end #--------------------------------------------------------------------------- # * Redefined method: product #--------------------------------------------------------------------------- unless method_defined?(:product) def product(*arrays) (e = "(result = []) && self.each {|i0| ") && (a = arrays.size).times {|i| e += "arrays[#{i}].each {|i#{i+1}| " } (e += "result.push([i0,") && a.times {|i| e += "i#{i+1}," } (e += "])}" + "}" * a + " && result" ) return eval(e) end end #--------------------------------------------------------------------------- # * New method: geometric_average #--------------------------------------------------------------------------- unless method_defined?(:geometric_average) def geometric_average(float = false) average = empty? ? 0 : num_times ** (1.0 / size) return (float ? average : average.to_i) end end #--------------------------------------------------------------------------- # * New method: average #--------------------------------------------------------------------------- unless method_defined?(:average) def average(float = false) sum / [(float ? size.to_f : size.to_i), 1].max end end #--------------------------------------------------------------------------- # * Alias method #--------------------------------------------------------------------------- alias_sec_method :has_all?, :have_all? alias_sec_method :has_any?, :have_any? end #============================================================================== # ** Hash #------------------------------------------------------------------------------ # #============================================================================== class Hash #-------------------------------------------------------------------------- # * Define Secondary Listing #-------------------------------------------------------------------------- define_sec_method(:reverse!) { self.dup == replace(reverse) ? nil : self } #-------------------------------------------------------------------------- # ● New method: reverse #-------------------------------------------------------------------------- unless method_defined?(:reverse) def reverse key, new_hash = self.keys, {} key.reverse.each_with_index {|k,i| new_hash[k] = self[key[i]]} new_hash end end #-------------------------------------------------------------------------- # ● New method: recursive_clone #-------------------------------------------------------------------------- unless method_defined?(:rclone) def recursive_clone (clon = self.clone).each_key do |i| clon[i] = clon[i].recursive_clone rescue clon[i].clone rescue clon[i] end clon end alias_method(:rclone, :recursive_clone) end #-------------------------------------------------------------------------- # ● New method: deep #-------------------------------------------------------------------------- unless method_defined?(:deep) def deep(deep = -1) tmp_deep = deep + 1 key_deep = tmp_deep value_deep = tmp_deep self.each do |k, v| key_deep = k.deep(tmp_deep) if key_deep < k.deep(tmp_deep) rescue nil value_deep = v.deep(tmp_deep)if value_deep< v.deep(tmp_deep) rescue nil end key_deep > value_deep ? key_deep : value_deep end end #-------------------------------------------------------------------------- # ● New method: fusion #-------------------------------------------------------------------------- unless method_defined?(:fusion) def fusion (array = sort).each_index do |i| array[i] = array[i][0] + array[i][1] rescue array[i] end array end end end #============================================================================== # ** NilClass #------------------------------------------------------------------------------ # #============================================================================== class NilClass #-------------------------------------------------------------------------- # ● Overwriten method: clone, dup #-------------------------------------------------------------------------- define_method(:clone) {|*a|} define_method(:dup) {|*a|} end #============================================================================== # ** Math #------------------------------------------------------------------------------ # #============================================================================== module Math #-------------------------------------------------------------------------- # ● New method: radian2degree #-------------------------------------------------------------------------- def self.radian2degree(r) r * 180 / Math::PI end #-------------------------------------------------------------------------- # ● New method: degree2radian #-------------------------------------------------------------------------- def self.degree2radian(g) g * Math::PI / 180 end #-------------------------------------------------------------------------- # ● New method: A (Ackermann function) #-------------------------------------------------------------------------- def self.A(m,n) text = 'Ackermann: No negative values allowed.' if m < 0 or n < 0 raise ArgumentError.new(text) if m < 0 or n < 0 return n + 1 if m == 0 return Math.A(m - 1, 1) if n == 0 return Math.A(m - 1, Math.A(m, n - 1)) end #-------------------------------------------------------------------------- # ● Constant #-------------------------------------------------------------------------- for i in 0..360 (@cos ||= {})[i] = Math.cos(Math.degree2radian(i - 90)) (@sin ||= {})[i] = Math.sin(Math.degree2radian(i - 90)) end #-------------------------------------------------------------------------- # ● New method: quick_cos #-------------------------------------------------------------------------- def self.quick_cos(i) @cos[i.round % 360] end #-------------------------------------------------------------------------- # ● New method: quick_sin #-------------------------------------------------------------------------- def self.quick_sin(i) @sin[i.round % 360] end #-------------------------------------------------------------------------- # ● New method: percent #-------------------------------------------------------------------------- def self.percent(min,max=100) min / max.to_f * 100.0 end end #============================================================================== # ** Numeric #------------------------------------------------------------------------------ # #============================================================================== class Numeric #-------------------------------------------------------------------------- # ● New method: group #-------------------------------------------------------------------------- unless method_defined?(:group) def group self.to_s.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2') end end end #============================================================================== # ** Float #------------------------------------------------------------------------------ # #============================================================================== class Float #-------------------------------------------------------------------------- # ● New method: float_points #-------------------------------------------------------------------------- unless method_defined?(:float_points) def float_points(points = 2) n = self * 10 ** points n = n.round.to_f / (10.0 ** points) return n end end end #============================================================================== # ** Color #------------------------------------------------------------------------------ # #============================================================================== class Color #---------------------------------------------------------------------------- # ● class << self #---------------------------------------------------------------------------- class << self #-------------------------------------------------------------------------- # ● Define Secondary Listing: red, green, blue, white, black... etc #-------------------------------------------------------------------------- define_sec_method(:red) {|*a| Color.new(255, 0, 0,a.first||255)} define_sec_method(:green) {|*a| Color.new( 0,255, 0,a.first||255)} define_sec_method(:blue) {|*a| Color.new( 0, 0,255,a.first||255)} define_sec_method(:white) {|*a| Color.new(255,255,255,a.first||255)} define_sec_method(:black) {|*a| Color.new( 0, 0, 0,a.first||255)} define_sec_method(:yellow) {|*a| Color.new(255,255, 0,a.first||255)} define_sec_method(:magenta) {|*a| Color.new(255, 0,255,a.first||255)} define_sec_method(:cyan) {|*a| Color.new( 0,255,255,a.first||255)} define_sec_method(:purple) {|*a| Color.new(128, 0,128,a.first||255)} define_sec_method(:gray) {|*a| Color.new(128,128,128,a.first||255)} define_sec_method(:lgray) {|*a| Color.new(211,211,211,a.first||255)} define_sec_method(:dgray) {|*a| Color.new( 64, 64, 64,a.first||255)} define_sec_method(:pink) {|*a| Color.new(255,175,175,a.first||255)} define_sec_method(:orange) {|*a| Color.new(255,165, 0,a.first||255)} define_sec_method(:brown) {|*a| Color.new(128, 64, 0,a.first||255)} define_sec_method(:chocolate){|*a| Color.new(210,105, 30,a.first||255)} define_sec_method(:golden) {|*a| Color.new(218,165, 32,a.first||255)} define_sec_method(:silver) {|*a| Color.new(192,192,192,a.first||255)} define_sec_method(:normal) { white } define_sec_method(:disabled) { white(128)} define_sec_method(:erase) { Color.new(0,0,0,0)} define_sec_method(:system) {|*a| Color.new(192,224,255,a.first||255)} define_sec_method(:crisis) {|*a| Color.new(255,255, 64,a.first||255)} define_sec_method(:knockout) {|*a| Color.new(255, 64, 0,a.first||255)} #-------------------------------------------------------------------------- # ● Alias method: grey, light_grey, dark_grey #-------------------------------------------------------------------------- alias_sec_method :grey, :gray alias_sec_method :lightgrey, :lightgray, :light_grey, :light_gray, :lgray alias_sec_method :darkgrey, :darkgray, :dark_grey, :dark_gray, :dgray #-------------------------------------------------------------------------- # ● New method: method_missing #-------------------------------------------------------------------------- def method_missing(val,*a) val = "#{val}".gsub(/x/i,'') if "#{val}".size == 6 && "#{val}".gsub(/(\d+|[a-f])/i,'') r = "#{val}"[0..1].hex g = "#{val}"[2..3].hex b = "#{val}"[4..5].hex return Color.new(r,g,b,a.first||255) end text = "Undefined method #{val} at #{self.inspect}" raise(NoMethodError, text, caller(1)) end end #-------------------------------------------------------------------------- # ● Define Secondary Listing #-------------------------------------------------------------------------- define_sec_method(:invert) { set(255-red, 255-green, 255-blue, alpha)} #---------------------------------------------------------------------------- # * New method: to_hex #---------------------------------------------------------------------------- def to_hex str = [self.blue.to_i, self.green.to_i, self.red.to_i].pack("C*") str.inspect.gsub('\\x','') end end #============================================================================== # ** Viewport #------------------------------------------------------------------------------ # #============================================================================== class Viewport unless method_defined?(:disposed?) #-------------------------------------------------------------------------- # ● Alias Listing #-------------------------------------------------------------------------- alias_sec_method :d3x40932s2, :dispose #-------------------------------------------------------------------------- # ● New method: disposed? # help file is lying when says Viewport#disposed? is exist #-------------------------------------------------------------------------- define_method(:disposed?) { @disposed == true } #-------------------------------------------------------------------------- # ● Aliased method: dispose #-------------------------------------------------------------------------- def dispose(*a) (disposed? || d3x40932s2(*a) || 0) && @disposed = true end end #-------------------------------------------------------------------------- # ● New method: resize #-------------------------------------------------------------------------- define_sec_method(:resize) do |*a| self.rect = a.first.is_a?(Rect) ? a.first : Rect.new(*a) end #-------------------------------------------------------------------------- # * New method: update_viewport_sizes #-------------------------------------------------------------------------- define_sec_method(:update_viewport_sizes) do |*a| map = $game_map w, h = Graphics.width, Graphics.height hor = map.respond_to?(:loop_horizontal?) && map.loop_horizontal? ver = map.respond_to?(:loop_vertical?) && map.loop_vertical? dx = w > map.width * 32 && !hor ? (w - map.width * 32) / 2 : 0 dw = hor ? w : [w, map.width * 32].min dy = h > map.height * 32 && !ver ? (h - map.height * 32) / 2 : 0 dh = ver ? h : [h, map.height * 32].min resize(Rect.new(dx, dy, dw, dh)) end #-------------------------------------------------------------------------- # ● New method: x, y, width, height #-------------------------------------------------------------------------- define_sec_method(:x) { self.rect.x } define_sec_method(:y) { self.rect.y } define_sec_method(:width) { self.rect.width } define_sec_method(:height) { self.rect.height } define_sec_method(:x=) {|x2| resize(x2,y,width,height) } define_sec_method(:y=) {|y2| resize(x,y2,width,height) } define_sec_method(:width=) {|w1| resize(x,y,w1,height) } define_sec_method(:height=) {|h1| resize(x,y,width,h1) } end #============================================================================== # ** Graphics #------------------------------------------------------------------------------ # This module handles all Graphics #============================================================================== class << Graphics #------------------------------------------------------------------------ # ● Public Instance Variables #------------------------------------------------------------------------ attr_sec_accessor :auto_update, "[]" #------------------------------------------------------------------------ # ● Redirect Listing #------------------------------------------------------------------------ redirect_method :width, 'LiTTleDRAgo.client_size.at(0)' redirect_method :height, 'LiTTleDRAgo.client_size.at(1)' redirect_method :snap_to_bitmap, 'LiTTleDRAgo.snap_to_bitmap' redirect_method :disable_alt_enter, 'LiTTleDRAgo.disable_alt_enter' redirect_method :always_on_top, 'LiTTleDRAgo.always_on_top' redirect_method :show_fps, 'LiTTleDRAgo.show_fps' redirect_method :scale_screen, 'LiTTleDRAgo.scale_screen' redirect_method :fill_monitor, 'LiTTleDRAgo.fill_monitor' redirect_method :window, 'LiTTleDRAgo.window' redirect_method :toggle, 'LiTTleDRAgo.toggle' redirect_method :fullscreen, 'LiTTleDRAgo.fullscreen' redirect_method :fullscreen?, 'LiTTleDRAgo.fullscreen?' redirect_method :control_screen_size,'LiTTleDRAgo.control_screen_size' redirect_method :high_priority, 'LiTTleDRAgo.high_priority' redirect_method :high_priority=, 'LiTTleDRAgo.high_priority=args.at(0)' #------------------------------------------------------------------------ # ● Alias Listing #------------------------------------------------------------------------ alias_sec_method :resize_screen, :scale_screen alias_sec_method :alibrary_update, :update #------------------------------------------------------------------------ # ● Aliased method: update #------------------------------------------------------------------------ def update(*a) alibrary_update(*a) defined?(Scheduler.update) && Scheduler.update auto_update.each do |k| k[0].method(k[1]).call k[2].nil? || (k[2] -= 1) k[2].nil? || (k[2] <= 0 && k = nil) end auto_update.delete_if {|x| (x[2] || 1) <= 0 } end #-------------------------------------------------------------------------- # * New method: fadeoutviewport #-------------------------------------------------------------------------- def fadeoutviewport unless @fadeoutviewport @fadeoutviewport = Viewport.new(0,0,width,height) @fadeoutviewport.z = 0x3FFFFFFF @fadeoutviewport.color = Color.new(0,0,0,0) end @fadeoutviewport end #-------------------------------------------------------------------------- # ● Redefined method: wait, brightness #-------------------------------------------------------------------------- define_sec_method(:wait) { |frame| frame.times {|i| update } } define_sec_method(:brightness) { (255 - fadeoutviewport.color.alpha) } #-------------------------------------------------------------------------- # * Redefined method: brightness= (Set Graphics Brightness) #-------------------------------------------------------------------------- unless method_defined?(:brightness=) def brightness=(value) value = [[value, 0].max, 255].min fadeoutviewport.color.alpha = 255 - value end end #-------------------------------------------------------------------------- # * Redefined method: fadein (Graphics Fade In) # frame : frame of fade #-------------------------------------------------------------------------- unless method_defined?(:fadein) def fadein(frames = 10) return if frames <= 0 curvalue, count = brightness, (255 - brightness) frames.times do |i| (self.brightness = curvalue + (count * i / frames)) && update end end end #-------------------------------------------------------------------------- # * Redefined method: fadeout (Graphics Fade Out) # frame : frame of fade #-------------------------------------------------------------------------- unless method_defined?(:fadeout) def fadeout(frames = 10) return if frames <= 0 curvalue = count = self.brightness frames.times do |i| (self.brightness = curvalue - (count * i / frames)) && update end end end #-------------------------------------------------------------------------- # * New method: wait_for_input #-------------------------------------------------------------------------- unless method_defined?(:wait_for_input) def wait_for_input [Input,self].update [Input,self].update until press_any_key end end end #============================================================================== # ** Input #------------------------------------------------------------------------------ # This module handles all Input #============================================================================== class << Input #-------------------------------------------------------------------------- # ● Aliased Method: press?, :repeat?, :trigger? #-------------------------------------------------------------------------- [:press?,:repeat?,:trigger?].each do |method| next unless method_defined?(:"#{method}") alias_sec_method(:"sym_#{method}", :"#{method}") define_method(:"#{method}") do |*a| (b = a.first).is_a?(Symbol) && a[0] = eval("Input::#{b}") (a.first.not.nil?) && send(:"sym_#{method}", *a) end end end #============================================================================== # ** Spriteset_Map #------------------------------------------------------------------------------ # This class brings together map screen sprites, tilemaps, etc. # It's used within the Scene_Map class. #============================================================================== class Spriteset_Map #-------------------------------------------------------------------------- # ● New method: sprite_player #-------------------------------------------------------------------------- define_sec_method(:sprite_player) { find_character($game_player) } #-------------------------------------------------------------------------- # * Aliased method: update #-------------------------------------------------------------------------- unless method_defined?(:drg_spriteset_viewport_adjust) alias_sec_method :drg_spriteset_viewport_adjust, :update def update(*a) if viewport_size_change? @viewport_map_width = $game_map.width @viewport_map_height = $game_map.height @viewport_screen_width = Graphics.width @viewport_screen_height = Graphics.height [@viewport1,@viewport2,@viewport3].compact.update_viewport_sizes end drg_spriteset_viewport_adjust(*a) end end #-------------------------------------------------------------------------- # * New method: viewport_size_change? #-------------------------------------------------------------------------- unless method_defined?(:viewport_size_change?) def viewport_size_change? return true if @viewport_map_width != $game_map.width return true if @viewport_map_height != $game_map.height return true if @viewport_screen_width != Graphics.width return true if @viewport_screen_height != Graphics.height end end #-------------------------------------------------------------------------- # ● New method: redraw_character_sprites #-------------------------------------------------------------------------- unless method_defined?(:redraw_character_sprites) def redraw_character_sprites return refresh_characters if self.respond_to?(:refresh_characters) (@character_sprites ||= []).dispose @character_sprites = $game_map.events.keys.sort.map {|i| Sprite_Character.new(@viewport1, $game_map.events[i]) } + [Sprite_Character.new(@viewport1, $game_player)] end end #-------------------------------------------------------------------------- # ● New method: find_character #-------------------------------------------------------------------------- unless method_defined?(:find_character) def find_character(char) @character_sprites.detect { |s| s.character == char } end end end #============================================================================== # ** Game_Battler #------------------------------------------------------------------------------ # This class deals with battlers. It's used as a superclass for the Game_Actor # and Game_Enemy classes. #============================================================================== class Game_Battler #-------------------------------------------------------------------------- # ● New method: alive? #-------------------------------------------------------------------------- define_sec_method(:alive?) { self.not.dead? } #-------------------------------------------------------------------------- # ● New method: hp_percent #-------------------------------------------------------------------------- unless method_defined?(:hp_percent) def hp_percent(integer = false, float_points = 2) n = (hp / ((respond_to?(:mhp) ? mhp : maxhp) * 100.0)) return integer ? Integer(n) : n.float_points(float_points) end end #-------------------------------------------------------------------------- # ● New method: sp_percent #-------------------------------------------------------------------------- unless method_defined?(:sp_percent) def sp_percent(integer = false, float_points = 2) n = ((respond_to?(:sp) ? sp : mp) / ((respond_to?(:mmp) ? mmp : (respond_to?(:maxsp) ? maxsp : maxmp)) * 100.0)) return integer ? Integer(n) : n.float_points(float_points) end alias_method :mp_percent, :sp_percent end end #============================================================================== # ** InterpreterScriptCalls #------------------------------------------------------------------------------ # #============================================================================== module InterpreterScriptCalls #-------------------------------------------------------------------------- # ● Class Variables #-------------------------------------------------------------------------- @@scriptcommands = Hash.new { |h, k| prepare_script(k) } #-------------------------------------------------------------------------- # ● New method: self.prepare_script #-------------------------------------------------------------------------- def self.prepare_script(code) sym = :"$#{@@scriptcommands.length + 1}th_script" module_eval("define_method(:'#{sym}') { #{code} \n }") return (@@scriptcommands[code] = sym) end #-------------------------------------------------------------------------- # ● Overwriten method: eval #-------------------------------------------------------------------------- def eval(code, *a) return a.empty? ? send(@@scriptcommands[code]) : super(code, *a) end end #============================================================================== # ** Game_Character #------------------------------------------------------------------------------ # This class deals with characters. It's used as a superclass for the # Game_Player and Game_Event classes. #============================================================================== class Game_Character #-------------------------------------------------------------------------- # ● Include InterpreterScriptCalls #-------------------------------------------------------------------------- include(InterpreterScriptCalls) #-------------------------------------------------------------------------- # ● Redirect Listing #-------------------------------------------------------------------------- redirect_method :move_down, 'move_straight(2,*args)' redirect_method :move_left, 'move_straight(4,*args)' redirect_method :move_right, 'move_straight(6,*args)' redirect_method :move_up, 'move_straight(8,*args)' redirect_method :turn_down, 'set_direction(2,*args)' redirect_method :turn_left, 'set_direction(4,*args)' redirect_method :turn_right, 'set_direction(6,*args)' redirect_method :turn_up, 'set_direction(8,*args)' redirect_method :move_lower_left, 'move_diagonal(4, 2,*args)' redirect_method :move_lower_right, 'move_diagonal(6, 2,*args)' redirect_method :move_upper_left, 'move_diagonal(4, 8,*args)' redirect_method :move_upper_right, 'move_diagonal(6, 8,*args)' redirect_method :character_sprite, '$game_map.character_sprite(self)' redirect_method :character_above?, '(args.first.y > @y)' redirect_method :character_below?, '(args.first.y < @y)' redirect_method :character_right?, '(args.first.x < @x)' redirect_method :character_left?, '(args.first.x > @x)' redirect_method :pos, '[@x, @y]' redirect_method :pos_nt?, '!@through && pos?' redirect_method :normal_priority?, '@character_name != ""' redirect_method :map_passable?, '$game_map.passable?' #-------------------------------------------------------------------------- # * Redefined method: pos? # anime # reverse_dir #-------------------------------------------------------------------------- define_sec_method(:reverse_dir) {|dir| 10 - dir } define_sec_method(:pos?) {|x,y| @x == x && @y == y } define_sec_method(:anime) {|aid| @animation_id = aid } #-------------------------------------------------------------------------- # ● Redefined method: check_event_trigger_touch_front #-------------------------------------------------------------------------- unless method_defined?(:check_event_trigger_touch_front) def check_event_trigger_touch_front x2 = $game_map.round_x_with_direction(@x, @direction) y2 = $game_map.round_y_with_direction(@y, @direction) check_event_trigger_touch(x2, y2) end end #-------------------------------------------------------------------------- # ● Redefined method: move_straight #-------------------------------------------------------------------------- unless method_defined?(:move_straight) def move_straight(d, turn_ok = true) if passable?(@x, @y, d) set_direction(d) @x = $game_map.round_x_with_direction(@x, d) @y = $game_map.round_y_with_direction(@y, d) increase_steps elsif turn_ok set_direction(d) check_event_trigger_touch_front end end end #-------------------------------------------------------------------------- # ● Redefined method: set_direction #-------------------------------------------------------------------------- unless method_defined?(:set_direction) def set_direction(d) @direction = d unless @direction_fix || d == 0 @stop_count = 0 end end #-------------------------------------------------------------------------- # ● Redefined method: set_graphic #-------------------------------------------------------------------------- unless method_defined?(:set_graphic) def set_graphic(character_name, character_index = 0) @tile_id = 0 @character_name = character_name if self.respond_to?(:character_index) @character_index = character_index else @character_hue = character_index end @original_pattern = 1 end end #-------------------------------------------------------------------------- # ● Redefined method: swap #-------------------------------------------------------------------------- unless method_defined?(:swap) def swap(character) new_pos = character.pos character.moveto(x, y) moveto(*new_pos) end end #-------------------------------------------------------------------------- # ● Redefined method: rotate_swap_prev #-------------------------------------------------------------------------- unless method_defined?(:rotate_swap_prev) def rotate_swap_prev(*character) character.unshift(self) position = character.collect {|c| c.pos} character.each_with_index { |c,i| c.moveto(*position[i-1]) } end end #-------------------------------------------------------------------------- # ● Redefined method: rotate_swap_next #-------------------------------------------------------------------------- unless method_defined?(:rotate_swap_next) def rotate_swap_next(*character) character.unshift(self) position = character.collect {|c| c.pos} character.each_with_index do |char,index| i = index + 1 char.moveto(*position[i >= position.size ? 0 : i]) end end end #-------------------------------------------------------------------------- # ● New method: distance_from #-------------------------------------------------------------------------- unless method_defined?(:distance_from) def distance_from(character,type= 'xy') character = $game_map.events[character] if character.is_a?(Integer) return 0 if character.nil? return (@x - character.x).abs if type.to_s == 'x' return (@y - character.y).abs if type.to_s == 'y' return Math.hypot(@x - character.x, @y - character.y) end end #-------------------------------------------------------------------------- # * Redefined method: distance_x_from #-------------------------------------------------------------------------- unless method_defined?(:distance_x_from) def distance_x_from(x) result = @x - x if result.abs > $game_map.width / 2 result += result < 0 ? $game_map.width : -$game_map.width end result end end #-------------------------------------------------------------------------- # * Redefined method: distance_y_from #-------------------------------------------------------------------------- unless method_defined?(:distance_y_from) def distance_y_from(y) result = @y - y if result.abs > $game_map.height / 2 result += result < 0 ? $game_map.height : -$game_map.height end result end end #-------------------------------------------------------------------------- # ● New method: random_teleport #-------------------------------------------------------------------------- unless method_defined?(:random_teleport) def random_teleport 1000.times do moveto(rand($game_map.height), rand($game_map.width)) vx = LiTTleDRAgo::VX && !LiTTleDRAgo::VXA arg = vx ? [@x,@y] : [@x,@y,@direction] break if passable?(*arg) end || true end end #-------------------------------------------------------------------------- # * Redefined method: diagonal_passable? (for RMXP) # horz : Horizontal (4 or 6) # vert : Vertical (2 or 8) #-------------------------------------------------------------------------- unless method_defined?(:diagonal_passable?) def diagonal_passable?(x, y, horz, vert) x2 = $game_map.round_x_with_direction(x, horz) y2 = $game_map.round_y_with_direction(y, vert) (passable?(x, y, vert) && passable?(x, y2, horz)) || (passable?(x, y, horz) && passable?(x2, y, vert)) end end #-------------------------------------------------------------------------- # * Redefined method: collide_with_characters? (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:collide_with_characters?) def collide_with_characters?(x, y) collide_with_events?(x, y) end end #-------------------------------------------------------------------------- # * Redefined method: collide_with_events? (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:collide_with_events?) def collide_with_events?(x, y) $game_map.events_xy_nt(x, y).any? do |event| event.normal_priority? || self.is_a?(Game_Event) end end end #-------------------------------------------------------------------------- # * Redefined method: debug_through? #-------------------------------------------------------------------------- unless method_defined?(:debug_through?) def debug_through? debug = LiTTleDRAgo::VX ? $TEST : $DEBUG return debug && Input.press?(Input::CTRL) if self.is_a?(Game_Player) return false end end end #============================================================================== # ** Game_Actor #------------------------------------------------------------------------------ # This class handles actors. It is used within the Game_Actors class # ($game_actors), also referenced from the Game_Party class ($game_party). #============================================================================== class Game_Actor #-------------------------------------------------------------------------- # * Get Actor Object #-------------------------------------------------------------------------- define_sec_method(:actor) { $data_actors[@actor_id] } define_sec_method(:class) { $data_classes[@class_id] } end #============================================================================== # ** Game_Enemy #------------------------------------------------------------------------------ # This class handles enemies. It used within the Game_Troop class # ($game_troop). #============================================================================== class Game_Enemy #-------------------------------------------------------------------------- # * Get Enemy Object #-------------------------------------------------------------------------- define_sec_method(:enemy) { $data_enemies[@enemy_id] } end #============================================================================== # ** Game_Player #------------------------------------------------------------------------------ # This class handles the player. It includes event starting determinants and # map scrolling functions. The instance of this class is referenced by # $game_player. #============================================================================== class Game_Player #-------------------------------------------------------------------------- # ● Redefined method: actor # name #-------------------------------------------------------------------------- define_sec_method(:actor) { $game_party.leader } define_sec_method(:name) { actor.name } #-------------------------------------------------------------------------- # ● New method: method_missing #-------------------------------------------------------------------------- def method_missing(val,*a,&b) return actor.send(val.to_s,*a,&b) if actor.respond_to?(val.to_sym) text = "Undefined method #{val} at #{self.inspect}" raise(NoMethodError, text, caller(1)) end end #============================================================================== # ** Game_Event #------------------------------------------------------------------------------ # This class deals with events. It handles functions including event page # switching via condition determinants, and running parallel process events. # It's used within the Game_Map class. #============================================================================== class Game_Event < Game_Character #-------------------------------------------------------------------------- # ● Public Instance Variables #-------------------------------------------------------------------------- method_defined?(:erased) || (attr_reader :erased) method_defined?(:id) || (attr_reader :id) method_defined?(:event) || (attr_reader :event) #-------------------------------------------------------------------------- # ● New method: name # ● New method: restore #-------------------------------------------------------------------------- define_sec_method(:name) { @event.name } define_sec_method(:restore) { (@erased = false) || refresh } #-------------------------------------------------------------------------- # ● New method: destroy #-------------------------------------------------------------------------- unless method_defined?(:destroy) def destroy (m = $game_map).events.reject! {|e| e == @id} (s = m.spriteset).is_a?(Spriteset_Map) && s.redraw_character_sprites end end #-------------------------------------------------------------------------- # ● New method: eliminate #-------------------------------------------------------------------------- unless method_defined?(:eliminate) def eliminate (eliminate = $game_map.eliminate_event)[(id = $game_map.map_id)] ||= [] (eliminate[id].include?(@id) || eliminate[id].push(@id)) && destroy end end #-------------------------------------------------------------------------- # ● New method: note #-------------------------------------------------------------------------- unless method_defined?(:note) def note list = @page ? @page.list.select {|l| [108,408].include?(l.code)} : [] notes = list.collect {|l| l.parameters[0] }.join("\n") return notes end end #-------------------------------------------------------------------------- # ● New method: proper_page_index #-------------------------------------------------------------------------- unless method_defined?(:proper_page_index) def proper_page_index if respond_to?(:conditions_met?) page = respond_to?(:find_proper_page) ? find_proper_page : @event.pages.reverse.find {|page| conditions_met?(page)} (i = @event.pages.index(page)).is_a?(Integer) ? i + 1 : 0 end end end end #============================================================================== # ** Game_Party #------------------------------------------------------------------------------ # This class handles the party. It includes information on amount of gold # and items. Refer to "$game_party" for the instance of this class. #============================================================================== class Game_Party #-------------------------------------------------------------------------- # ● Alias Listing #-------------------------------------------------------------------------- alias_sec_method :drg_ce_item_number, :item_number #-------------------------------------------------------------------------- # ● Redirect Listing #-------------------------------------------------------------------------- redirect_method :player_pos, '($game_player.pos)' redirect_method :leader, '(members.first)' redirect_method :members, '(actors)' redirect_method :actors, '(members)' #-------------------------------------------------------------------------- # ● New method: existing_actors, recover_all #-------------------------------------------------------------------------- define_sec_method(:existing_actors) { members.find_all {|a| a.exist?} } define_sec_method(:recover_all) { members.each {|a| a.recover_all} } #-------------------------------------------------------------------------- # ● New method: has_actors? #-------------------------------------------------------------------------- unless method_defined?(:has_actors?) def has_actors?(*a) party = @actors.collect {|s| s.is_a?(Game_Actor) ? s.id : s } actor = a.collect {|s| s.is_a?(Game_Actor) ? s.id : s }.flatten return party.have_all?(*actor) end end #-------------------------------------------------------------------------- # ● New method: has_any_actors? #-------------------------------------------------------------------------- unless method_defined?(:has_any_actors?) def has_any_actors?(*a) party = @actors.collect {|s| s.is_a?(Game_Actor) ? s.id : s } actor = a.collect {|s| s.is_a?(Game_Actor) ? s.id : s }.flatten return party.have_any?(*actor) end end #-------------------------------------------------------------------------- # ● New method: swap_previous_actor #-------------------------------------------------------------------------- unless method_defined?(:swap_leader_prev) def swap_leader_prev(n = 1) n <= 0 || n.round.times { @actors.previous_item && drg_ce_refresh } n >= 0 || swap_leader_next(n.round.abs) end end #-------------------------------------------------------------------------- # ● New method: swap_next_actor #-------------------------------------------------------------------------- unless method_defined?(:swap_leader_next) def swap_leader_next(n = 1) n <= 0 || n.round.times { @actors.next_item && drg_ce_refresh } n >= 0 || swap_leader_prev(n.round.abs) end end #-------------------------------------------------------------------------- # ● New method: set_leader #-------------------------------------------------------------------------- unless method_defined?(:set_leader) def set_leader(id) actor = id.is_a?(Numeric) ? $game_actors[id.to_i] : id if actor.is_a?(Game_Actor) && has_actors?(actor.id) swap_leader_next until $game_party.leader.id == actor.id actor.id end end end #-------------------------------------------------------------------------- # ● New method: drg_ce_refresh #-------------------------------------------------------------------------- unless method_defined?(:drg_ce_refresh) def drg_ce_refresh return refresh if respond_to?(:refresh) return ($game_map.need_refresh = true) && $game_player.refresh end end #-------------------------------------------------------------------------- # * Get Party Name #-------------------------------------------------------------------------- unless method_defined?(:name) def name return "" if existing_actors.size == 0 return leader.name if existing_actors.size == 1 return "#{leader.name}'s Party" end end #-------------------------------------------------------------------------- # * Aliased method: item_number #-------------------------------------------------------------------------- def item_number(item) unless LiTTleDRAgo::VX return drg_ce_item_number(item.id) if item.is_a?(RPG::Item) return weapon_number(item.id) if item.is_a?(RPG::Weapon) return armor_number(item.id) if item.is_a?(RPG::Armor) else item = $data_items[item.to_i] if item.is_a?(Numeric) end return skill_number(item) if item.is_a?(RPG::Skill) return drg_ce_item_number(item) end #-------------------------------------------------------------------------- # * Redefined method: weapon_number #-------------------------------------------------------------------------- unless method_defined?(:weapon_number) def weapon_number(weapon) weapon = $data_weapons[weapon.to_i] if weapon.is_a?(Numeric) item_number(weapon) end end #-------------------------------------------------------------------------- # * Redefined method: armor_number #-------------------------------------------------------------------------- unless method_defined?(:armor_number) def armor_number(armor) armor = $data_armors[armor.to_i] if armor.is_a?(Numeric) item_number(armor) end end #-------------------------------------------------------------------------- # * New method: skill_number #-------------------------------------------------------------------------- unless method_defined?(:skill_number) def skill_number(skill) skill = $data_skills[skill.to_i] if skill.is_a?(Numeric) s1 = actors.select {|a| a.skill_learn?(skill) } s2 = actors.select {|a| a.skill_learn?(skill.id) } return s1.size + s2.size end end #-------------------------------------------------------------------------- # * New method: gain_all_items #-------------------------------------------------------------------------- def gain_all_items(ammount=1) (0..999).to_a.each do |s| next if $data_items[s].nil? || $data_items[s].name == '' $game_party.drg_ce_get_item($data_items[s],ammount) end end #-------------------------------------------------------------------------- # * New method: gain_all_weapons #-------------------------------------------------------------------------- def gain_all_weapons(ammount=1) (0..999).to_a.each do |s| next if $data_weapons[s].nil? || $data_weapons[s].name == '' drg_ce_get_item($data_weapons[s],ammount) end end #-------------------------------------------------------------------------- # * New method: gain_all_armors #-------------------------------------------------------------------------- def gain_all_armors(ammount=1) (0..999).to_a.each do |s| next if $data_armors[s].nil? || $data_armors[s].name == '' drg_ce_get_item($data_armors[s],ammount) end end #-------------------------------------------------------------------------- # * New method: drg_ce_get_item #-------------------------------------------------------------------------- def drg_ce_get_item(item,ammount) return gain_item(item,ammount) if LiTTleDRAgo::VX return gain_item(item.id,ammount) if item.is_a?(RPG::Item) return gain_weapon(item.id,ammount) if item.is_a?(RPG::Weapon) return gain_armor(item.id,ammount) if item.is_a?(RPG::Armor) end end #============================================================================== # ** Game_Follower #------------------------------------------------------------------------------ # This class handles followers. A follower is an allied character, other than # the front character, displayed in the party. It is referenced within the # Game_Followers class. #============================================================================== class Game_Follower < Game_Character #-------------------------------------------------------------------------- # * Redirect Listing #-------------------------------------------------------------------------- redirect_method :name, "(actor.nil? ? '' : actor.name)" end if defined?(Game_Follower) #============================================================================== # ** Game_Map #------------------------------------------------------------------------------ # This class handles maps. It includes scrolling and passage determination # functions. The instance of this class is referenced by $game_map. #============================================================================== class Game_Map #-------------------------------------------------------------------------- # * Public Instance Variables #-------------------------------------------------------------------------- attr_sec_reader :eliminate_event, 'Hash.new' #-------------------------------------------------------------------------- # * Alias Listing #-------------------------------------------------------------------------- alias_sec_method :setup_eliminate_event, :setup #-------------------------------------------------------------------------- # ● New method: name, parent_id, base_parent_id # event_list , map_events #-------------------------------------------------------------------------- define_sec_method(:name) { mapInfo[@map_id].name } define_sec_method(:parent_id) { mapInfo[@map_id].parent_id } define_sec_method(:base_parent_id) { search_parent_id(mapInfo) } define_sec_method(:event_list) { events.values } define_sec_method(:map_events) { @map.events } define_sec_method(:screen) { $game_screen } define_sec_method(:loop_horizontal?) { false } define_sec_method(:loop_vertical?) { false } define_sec_method(:map_child?) { |*a| a & child_ids == a } #-------------------------------------------------------------------------- # * Aliased method: setup #-------------------------------------------------------------------------- def setup(*args) setup_eliminate_event(*args) events.reject! {|s| [eliminate_event[@map_id]].flatten.include?(s) } end #-------------------------------------------------------------------------- # * Redefined method: any_event_strarting? (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:any_event_starting?) def any_event_starting? event_list.any? {|event| event.starting } end end #-------------------------------------------------------------------------- # * Redefined method: interpreter (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:interpreter) def interpreter return $game_system.map_interpreter if LiTTleDRAgo.scene.is_a?(Scene_Map) return $game_system.battle_interpreter end end #-------------------------------------------------------------------------- # * Redefined method: events_xy (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:events_xy) def events_xy(x, y) event_list.select {|event| event.x == x && event.y == y } end end #-------------------------------------------------------------------------- # * Redefined method: events_xy_nt (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:events_xy_nt) def events_xy_nt(x, y) event_list.select {|event| event.pos_nt?(x, y) } end end #-------------------------------------------------------------------------- # * Redefined method: round_x (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:round_x) define_method(:round_x) {|x| loop_horizontal? ? (x + width) % width : x } end #-------------------------------------------------------------------------- # * Redefined method: round_y (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:round_y) define_method(:round_y) {|y| loop_vertical? ? (y + height) % height : y } end #-------------------------------------------------------------------------- # * Redefined method: x_with_direction (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:x_with_direction) def x_with_direction(x, d) x + (d == 6 ? 1 : d == 4 ? -1 : 0) end end #-------------------------------------------------------------------------- # * Redefined method: y_with_direction (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:y_with_direction) def y_with_direction(y, d) y + (d == 2 ? 1 : d == 8 ? -1 : 0) end end #-------------------------------------------------------------------------- # * Redefined method: round_x_with_direction (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:round_x_with_direction) def round_x_with_direction(x, d) round_x(x_with_direction(x, d)) end end #-------------------------------------------------------------------------- # * Redefined method: round_y_with_direction (for RMXP) #-------------------------------------------------------------------------- unless method_defined?(:round_y_with_direction) def round_y_with_direction(y, d) round_y(y_with_direction(y, d)) end end #-------------------------------------------------------------------------- # ● New method: existing_events #-------------------------------------------------------------------------- unless method_defined?(:existing_events) def existing_events result = event_list.select {|e| e.not.erased } return result end end #-------------------------------------------------------------------------- # ● New method: map_info #-------------------------------------------------------------------------- unless method_defined?(:mapInfo) def mapInfo(ext = data_default_extension) data = "Data/MapInfos.#{ext}" @mapinfo ||= load_data(sprintf("#{data}")) if File.exist?("#{data}") return @mapinfo end end #-------------------------------------------------------------------------- # ● New method: data_extension #-------------------------------------------------------------------------- unless method_defined?(:data_default_extension) def data_default_extension data = LiTTleDRAgo.read_ini('Game','Scripts') data = data.split('.').last || 'rxdata' return data end end #-------------------------------------------------------------------------- # ● New method: search_parent_id #-------------------------------------------------------------------------- unless method_defined?(:search_parent_id) def search_parent_id(mapInfo, id = @map_id, ancestor = 0) m_id = id loop do _m_id = mapInfo[m_id] p_id = _m_id.respond_to?(:parent_id) ? _m_id.parent_id : nil return p_id if p_id == nil return m_id if p_id == ancestor m_id = p_id end end end #-------------------------------------------------------------------------- # ● New method: base_map_name #-------------------------------------------------------------------------- unless method_defined?(:base_map_name) def base_map_name map = mapInfo[search_parent_id(mapInfo)] name = nil name ||= map.name if map.respond_to?(:name) return name || '' end end #-------------------------------------------------------------------------- # ● New method: child_ids #-------------------------------------------------------------------------- unless method_defined?(:child_ids) def child_ids mapInfo.keys.select {|map_id| mapInfo[map_id].parent_id == @map_id } end end #-------------------------------------------------------------------------- # ● New method: descendant? #-------------------------------------------------------------------------- unless method_defined?(:map_descendant?) def map_descendant?(*a) a.all? {|map_id| search_parent_id(mapInfo, map_id, @map_id)} end end #-------------------------------------------------------------------------- # ● New method: load_event #-------------------------------------------------------------------------- unless method_defined?(:load_event) def load_event(*a) case a.size when 5, 4 then (mapid, eventid, x, y = *a) when 3 then (mapid = @map_id) && (eventid, x, y = *a) when 2 then (mapid, y = @map_id, 0) && (eventid, x = *a) when 1 then (mapid, x, y = @map_id, 0,0) && (eventid = a.first) when 0 then return nil end map = load_map_data(mapid) event = map.events.values.detect { |event| event.id == eventid } unless event.nil? (a = a.at(4)) && (b = [a].flatten) && event.pages.reject! do |s| c = b.map {|i| i.is_a?(Range) ? i.to_a : i } c.flatten.not.include?(event.pages.index(s)+1) end return nil if event.pages.empty? c,r = [Array,Range], [] c.include?(x.class) && (x = x.to_a.map{|s|s.is_a?(Range) ? s.to_a : s}) c.include?(y.class) && (y = y.to_a.map{|s|s.is_a?(Range) ? s.to_a : s}) [x].flatten.each {|x1| ([y].flatten).each {|y1| event.instance_variable_set(:@id,(id = unused_key_events)) r.push(@events[id] = e = Game_Event.new(@map_id, event.clone)) e.moveto(x1,y1)}} a = r.size == 1 ? r.first : r a && (s = spriteset).is_a?(Spriteset_Map) && s.redraw_character_sprites return a end end end #-------------------------------------------------------------------------- # ● New method: call_event #-------------------------------------------------------------------------- unless method_defined?(:call_event) def call_event(*a) case a.size when 3 then (mapid, eventid, page_id = *a) when 2 then (page_id = -1) && (mapid, eventid = *a) when 1 then (mapid, page_id = @map_id, -1) && (eventid = a.first) when 0 then return nil end map = load_map_data(mapid) event = map.events.values.detect { |event| event.id == eventid } unless event.nil? if page_id == -1 && event.respond_to?(:conditions_met?) pages = event.pages.reverse.find {|page| event.conditions_met?(page)} else pages = event.pages[[page_id,1].max-1] end klass = LiTTleDRAgo::VX ? Game_Interpreter : Interpreter child = klass.new(interpreter.instance_variable_get(:@depth) + 1) child.setup(pages.list, interpreter.same_map? ? event.id : 0) if LiTTleDRAgo::VXA child.run rescue FiberError else interpreter.instance_variable_set(:@child_interpreter, child) end end end end #-------------------------------------------------------------------------- # ● New method: load_map_data #-------------------------------------------------------------------------- unless method_defined?(:load_map_data) def load_map_data(mapid, ext = nil) (ext.nil? || "#{ext}".empty?) && (ext = data_default_extension) (map = sprintf("Data/Map%03d.#{ext}", mapid)) && load_data(map) end end #-------------------------------------------------------------------------- # ● New method: unused_key_events #-------------------------------------------------------------------------- unless method_defined?(:unused_key_events) def unused_key_events (1..(@events.keys.max||0) + 1).detect {|i| @events.keys.not.include?(i)} end end #-------------------------------------------------------------------------- # ● New method: spriteset #-------------------------------------------------------------------------- unless method_defined?(:spriteset) def spriteset LiTTleDRAgo.scene.instance_variable_get(:@spriteset) end end #-------------------------------------------------------------------------- # ● New method: character_sprite #-------------------------------------------------------------------------- unless method_defined?(:character_sprite) def character_sprite(id = 0) return unless spriteset.is_a?(Spriteset_Map) id = id.is_a?(Game_Character) ? id : id == 0 ? $game_player : events[id] spriteset.find_character(id) end end #-------------------------------------------------------------------------- # ● New method: picture_sprite #-------------------------------------------------------------------------- unless method_defined?(:picture_sprite) def picture_sprite(id = nil) return unless spriteset.is_a?(Spriteset_Map) spriteset.update_pictures if spriteset.respond_to?(:update_pictures) result = spriteset.instance_variable_get(:@picture_sprites) id.nil? ? result : result[id] end end end #============================================================================== # ■ RPG::Cache #------------------------------------------------------------------------------ # #============================================================================== ModCache = LiTTleDRAgo.cache module ModCache #------------------------------------------------------------------------- # * Self #------------------------------------------------------------------------- class << self #----------------------------------------------------------------------- # ● New method: self.draw_text #----------------------------------------------------------------------- unless method_defined?(:draw_text) def draw_text( width, height, text, font = Font.default_name, size = Font.default_size, bold = Font.default_bold, italic = Font.default_italic, color = Font.default_color, edging = false ) cache_index = "text_" + width.to_s + height.to_s + text font_text = "" font.size.times do |i| font_text += font[i].to_s end cache_index += font_text + size.to_s + bold.to_s + italic.to_s cache_index += "#{color.red}#{color.blue}#{color.green}#{color.alpha}" @cache ||= {} if @cache[cache_index].nil? or @cache[cache_index].disposed? bitmap = Bitmap.new(width, height) bitmap.font.name = font bitmap.font.size = size bitmap.font.bold = bold bitmap.font.italic = italic bitmap.font.color = color if edging bitmap.draw_edging_text(0, 0, width, height, text, 0) else bitmap.draw_text(0, 0, width, height, text, 0) end @cache[cache_index] = bitmap end return @cache[cache_index] end end #----------------------------------------------------------------------- # ● New method: self.method_missing #----------------------------------------------------------------------- def method_missing(val,*a,&b) if a.at(0).is_a?(String) && a.size <= 2 return load_bitmap("Graphics/#{val}/",*a,&b) end text = "Undefined method #{val} at #{self.inspect}" raise(NoMethodError, text, caller(1)) end #----------------------------------------------------------------------- # ● New method: drago_get_bitmap #----------------------------------------------------------------------- def drago_get_bitmap(folder_name, filename = '', hue = 0) return empty_bitmap if filename.not.is_a?(String) || filename.empty? path = LiTTleDRAgo::APPPATHDRAGO + "#{folder_name}/" path = path.gsub("\\","/").gsub("//","/") last = filename.split('.').last filename.gsub!(".png","") if last.is_a?(String) && last[/png/i] load_bitmap_no_rescue(path.downcase,filename.downcase,hue) end #----------------------------------------------------------------------- # ● New method: drago_set_bitmap #----------------------------------------------------------------------- def drago_set_bitmap(bitmap, folder_name = '', filename = 'bitmap') path = LiTTleDRAgo::APPPATHDRAGO + "#{folder_name}/" path = path.gsub("\\","/").gsub("//","/") last = filename.split('.').last filename += '.png' unless last.is_a?(String) && last[/png/i] Dir.make_dir(path) unless FileTest.directory?(path) bitmap.export(path + filename) drago_get_bitmap(folder_name, filename) end #----------------------------------------------------------------------- # ● New method: drago_bitmap_exist? #----------------------------------------------------------------------- def drago_bitmap_exist?(folder_name, filename) return false if filename.not.is_a?(String) || filename.empty? path = LiTTleDRAgo::APPPATHDRAGO + "#{folder_name}/" path = path.gsub("\\","/").gsub("//","/") last = filename.split('.').last filename += '.png' unless last.is_a?(String) && last[/png/i] FileTest.file?(path + filename) end #-------------------------------------------------------------------------- # * Load Bitmap #-------------------------------------------------------------------------- define_sec_method(:load_bitmap_no_rescue) do |folder, file, *a| @cache ||= {} if file.empty? empty_bitmap elsif (hue = a.first).is_a?(Numeric) && hue != 0 hue_changed_bitmap(folder + file, hue.round) else normal_bitmap(folder + file) end end #-------------------------------------------------------------------------- # * Create Empty Bitmap #-------------------------------------------------------------------------- define_sec_method(:empty_bitmap) { Bitmap.new(32, 32)} #-------------------------------------------------------------------------- # * Create/Get Normal Bitmap #-------------------------------------------------------------------------- define_sec_method(:normal_bitmap) do |path| @cache[path] = Bitmap.new(path) unless include?(path) @cache[path] end #-------------------------------------------------------------------------- # * Create/Get Hue-Changed Bitmap #-------------------------------------------------------------------------- define_sec_method(:hue_changed_bitmap) do |path, hue| key = [path, hue] unless include?(key) @cache[key] = normal_bitmap(path).clone @cache[key].hue_change(hue) end @cache[key] end #-------------------------------------------------------------------------- # * Check Cache Existence #-------------------------------------------------------------------------- def include?(key) @cache[key] && @cache[key].not.disposed? end end end #============================================================================== # ** Window_Base #------------------------------------------------------------------------------ # This class is for all in-game windows. #============================================================================== class Window_Base < Window #-------------------------------------------------------------------------- # * Redirect Listing #-------------------------------------------------------------------------- redirect_method :draw_text, 'contents.draw_text' redirect_method :text_size, 'contents.text_size' redirect_method :change_color, 'contents.change_color' redirect_method :draw_picture, 'contents.draw_picture' redirect_method :draw_icon, 'contents.draw_icon' redirect_method :draw_battler, 'contents.draw_battler' #-------------------------------------------------------------------------- # * Redefined method: line_height, translucent_alpha # * New method: show, hide, activate, deactivate #-------------------------------------------------------------------------- define_sec_method(:line_height) { 32 } define_sec_method(:translucent_alpha) { 160 } define_sec_method(:show) { self.visible = true } define_sec_method(:hide) { self.visible = false } define_sec_method(:activate) { self.active = true } define_sec_method(:deactivate) { self.active = false } #-------------------------------------------------------------------------- # * New method: center_window #-------------------------------------------------------------------------- unless method_defined?(:center_window) def center_window self.x = Graphics.width/2 - self.width/2 self.y = Graphics.height/2 - self.height/2 end end #-------------------------------------------------------------------------- # * Redefined method: disabled_color #-------------------------------------------------------------------------- unless method_defined?(:disabled_color) def disabled_color color = normal_color color.alpha = 128 return color end end #-------------------------------------------------------------------------- # * Redefined method: draw_text_ex #-------------------------------------------------------------------------- unless method_defined?(:draw_text_ex) def draw_text_ex(x, y, text) reset_font_settings text = convert_escape_characters(text) pos = {:x => x, :y => y, :new_x => x, :height => calc_line_height(text)} process_character(text.slice!(0, 1), text, pos) until text.empty? end end #-------------------------------------------------------------------------- # * Redefined method: reset_font_settings #-------------------------------------------------------------------------- unless method_defined?(:reset_font_settings) def reset_font_settings change_color(normal_color) contents.font.size = Font.default_size contents.font.bold = Font.default_bold contents.font.italic = Font.default_italic end end #-------------------------------------------------------------------------- # * Redefined method: convert_escape_characters #-------------------------------------------------------------------------- unless method_defined?(:convert_escape_characters) def convert_escape_characters(text) result = text.to_s.clone result.gsub!(/\\/) { "\e" } result.gsub!(/\e\e/) { "\\" } result.gsub!(/\eV\[(\d+)\]/i) { $game_variables[$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!(/\eG/i) { currency_unit } result end end #-------------------------------------------------------------------------- # * Redefined method: actor_name #-------------------------------------------------------------------------- unless method_defined?(:actor_name) def actor_name(n) actor = n >= 1 ? $game_actors[n] : nil actor ? actor.name : "" end end #-------------------------------------------------------------------------- # * Redefined method: party_member_name #-------------------------------------------------------------------------- unless method_defined?(:party_member_name) def party_member_name(n) actor = n >= 1 ? $game_party.instance_variable_get(:@actors)[n - 1] : nil actor ? actor.name : "" end end #-------------------------------------------------------------------------- # * Redefined method: process_character #-------------------------------------------------------------------------- unless method_defined?(:process_character) def process_character(c, text, pos) case c when "\n" # New line process_new_line(text, pos) when "\f" # New page process_new_page(text, pos) when "\e" # Control character process_escape_character(obtain_escape_code(text), text, pos) else # Normal character process_normal_character(c, pos) end end end #-------------------------------------------------------------------------- # * Redefined method: process_normal_character #-------------------------------------------------------------------------- unless method_defined?(:process_normal_character) def process_normal_character(c, pos) text_width = text_size(c).width draw_text(pos[:x], pos[:y], text_width * 2, pos[:height], c) pos[:x] += text_width end end #-------------------------------------------------------------------------- # * Redefined method: process_new_line #-------------------------------------------------------------------------- unless method_defined?(:process_new_line) def process_new_line(text, pos) pos[:x] = pos[:new_x] pos[:y] += pos[:height] pos[:height] = calc_line_height(text) end end #-------------------------------------------------------------------------- # * Redefined method: process_new_page #-------------------------------------------------------------------------- unless method_defined?(:process_new_page) def process_new_page(text, pos) end end #-------------------------------------------------------------------------- # * Redefined method: obtain_escape_code #-------------------------------------------------------------------------- unless method_defined?(:obtain_escape_code) def obtain_escape_code(text) text.slice!(/^[\$\.\|\^!><\{\}\\]|^[\/\w+\/]+/i) end end #-------------------------------------------------------------------------- # * Redefined method: obtain_escape_param #-------------------------------------------------------------------------- unless method_defined?(:obtain_escape_param) def obtain_escape_param(text) text.slice!(/^\[\d+\]/)[/\d+/].to_i rescue 0 end end #-------------------------------------------------------------------------- # * Redefined method: process_escape_character #-------------------------------------------------------------------------- unless method_defined?(:process_escape_character) def process_escape_character(code, text, pos) case code.upcase when 'C' change_color(text_color(obtain_escape_param(text))) when 'I' process_draw_icon(obtain_escape_code(text), pos) when '{' make_font_bigger when '}' make_font_smaller end end end #-------------------------------------------------------------------------- # * Redefined method: process_draw_icon #-------------------------------------------------------------------------- unless method_defined?(:process_draw_icon) def process_draw_icon(icon_index, pos) icon_index = icon_index.to_i if icon_index.to_i.to_s == icon_index draw_icon(icon_index, pos[:x], pos[:y]) pos[:x] += 24 end end #-------------------------------------------------------------------------- # * Redefined method: make_font_bigger #-------------------------------------------------------------------------- unless method_defined?(:make_font_bigger) def make_font_bigger contents.font.size += 8 if contents.font.size <= 64 end end #-------------------------------------------------------------------------- # * Redefined method: make_font_smaller #-------------------------------------------------------------------------- unless method_defined?(:make_font_smaller) def make_font_smaller contents.font.size -= 8 if contents.font.size >= 16 end end #-------------------------------------------------------------------------- # * Redefined method: calc_line_height #-------------------------------------------------------------------------- unless method_defined?(:calc_line_height) 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}" result = [result, contents.font.size].max end contents.font.size = last_font_size if restore_font_size result end end #-------------------------------------------------------------------------- # * New method: currency_unit #-------------------------------------------------------------------------- unless method_defined?(:currency_unit) def currency_unit gold = $data_system.words.gold return gold end end #-------------------------------------------------------------------------- # ● New method: draw_map_name #-------------------------------------------------------------------------- unless method_defined?(:draw_map_name) def draw_map_name(x, y, width, height) map_id = $game_map.map_id mapInfo = $game_map.mapInfo draw_text(x, y, width, height, mapInfo[map_id].name.to_s) end end #-------------------------------------------------------------------------- # ● New method: draw_enter_text #-------------------------------------------------------------------------- unless method_defined?(:draw_enter_text) def draw_enter_text(x, y, width, height, text) info_box = text.split(/\n/) info_box.size.times do |i| draw_text( x, y + i * line_height, width, line_height, info_box[i]) break if (y + i * line_height) > (self.height - line_height) end end end #-------------------------------------------------------------------------- # ● New method: draw_picture_number #-------------------------------------------------------------------------- unless method_defined?(:draw_picture_number) def draw_picture_number(x, y, value, file_name,align = 0, space = 0, frame_max = 1,frame_index = 0) number_image = LiTTleDRAgo.cache.windowskin(file_name) frame_max = [frame_max, 1].max frame_index = frame_max - 1 if frame_index > frame_max - 1 align = [[align,2].min,0].max cw = number_image.width / 10 ch = number_image.height / frame_max h = ch * frame_index number = value.abs.to_s.split(//) case align when 0 then plus_x = (-cw + space) * number.size when 1 then plus_x = ((-cw + space) * number.size) / 2 when 2 then plus_x = 0 end for r in 0..number.size - 1 rect = Rect.new(cw * number[r].to_i, h, cw, ch) contents.blt(plus_x + x + ((cw - space) * r), y , number_image, rect) end number_image.dispose end end end #============================================================================== # ■ Bitmap #------------------------------------------------------------------------------ # #============================================================================== class Bitmap #---------------------------------------------------------------------------- # ● Constant #---------------------------------------------------------------------------- RtlMoveMemory_pi = LiTTleDRAgo.rtlmemory_pi RtlMoveMemory_ip = LiTTleDRAgo.rtlmemory_ip Blur_Setting = "{ 'offset' => 2, 'spacing' => 1, 'opacity' => 255 }" #---------------------------------------------------------------------------- # ● Public Instance Variables #---------------------------------------------------------------------------- attr_sec_accessor :blur_settings, Blur_Setting #---------------------------------------------------------------------------- # ● Redirect Listing #---------------------------------------------------------------------------- redirect_method :change_hue, :hue_change #------------------------------------------------------------------------- # ● Define Secondary Listing #------------------------------------------------------------------------- define_sec_method(:full_fill) { |color| fill_rect(rect, color) } #---------------------------------------------------------------------------- # ● Alias Listing #---------------------------------------------------------------------------- alias_sec_method :invert!, :reversing! alias_sec_method :grayscale!, :gray_scale! alias_sec_method :frost, :diffusion alias_sec_method :frost!, :diffusion! alias_sec_method :drg_ce_stretch_blt, :stretch_blt alias_sec_method :drg_ce_hue_change, :hue_change #---------------------------------------------------------------------------- # ● New method: address #---------------------------------------------------------------------------- unless method_defined?(:address) def address @address ||= ( RtlMoveMemory_pi.call(a="\0"*4, __id__*2+16, 4) RtlMoveMemory_pi.call(a, a.unpack('L')[0]+8, 4) RtlMoveMemory_pi.call(a, a.unpack('L')[0]+16, 4) a.unpack('L')[0] ) end end #---------------------------------------------------------------------------- # ● New method: export #---------------------------------------------------------------------------- unless method_defined?(:export) def export(filename) file = File.open(filename, 'wb') size, vxace = width * height * 4, LiTTleDRAgo::RGSS3 case format = File.extname(filename) when '.bmp' data = String.new RtlMoveMemory_pi.call(empty_rString_struct="\0"*16,data.__id__*2,16) flags = vxace ? 5267461 : 8199 klass = empty_rString_struct.unpack('@4L')[0] pack = [flags,klass,size,address].pack('L4') weiss = [size+54,0,54,40,width,height,1,32,0,size,0,0,0,0] RtlMoveMemory_ip.call(data.__id__*2, pack, 16) file.write("BM#{weiss.pack('L6S2L6')}") file.write(data) RtlMoveMemory_ip.call(data.__id__*2, empty_rString_struct, 16) when '.png' write_chunk = Proc.new do |chunk| file.write([(vxace ? chunk.bytesize : chunk.size)-4].pack('N')) file.write(chunk) file.write([Zlib.crc32(chunk)].pack('N')) end null_char, w4, i, byte = "\0", width*4, 0, 0 RtlMoveMemory_pi.call(data=null_char*size, address, size) t_Fx = 0 if vxace data.force_encoding('ASCII-8BIT') (0).step(size-4, 4) do |i| t_Fx += 1 Graphics.update if t_Fx % 10000 == 0 byte = data.getbyte(i) data.setbyte(i, data.getbyte(i+=2)) data.setbyte(i, byte) end else (0).step(size-4, 4) do |i| t_Fx += 1 Graphics.update if t_Fx % 10000 == 0 data[i,3] = data[i,3].reverse! end end deflate = Zlib::Deflate.new(9) (size-w4).step(0, -w4) {|i| deflate << null_char << data[i,w4]} file.write("\211PNG\r\n\32\n") write_chunk.call("IHDR#{[width,height,8,6,0,0,0].pack('N2C5')}") write_chunk.call("IDAT#{deflate.finish}") write_chunk.call('IEND') deflate.close when '' then print("Extension '#{filename}' is missing.") else print("'#{format}' is not supported.") end file.close end end #---------------------------------------------------------------------------- # ● New method: blt_cache #---------------------------------------------------------------------------- unless method_defined?(:blt_cache) def blt_cache(x, y, width, height, text, align, edging) cache_bitmap = LiTTleDRAgo.cache.draw_text( width, height, text, self.font.name, self.font.size, self.font.bold, self.font.italic, self.font.color, edging ) x_plus = uncache_align_exe(width, text, align) blt(x + x_plus , y , cache_bitmap, Rect.new(0, 0, width, height)) end end #---------------------------------------------------------------------------- # ● New method: uncache_align_exe #---------------------------------------------------------------------------- unless method_defined?(:uncache_align_exe) def uncache_align_exe(width, text, align) recter = self.text_size(text) case align when 0 then x_index = 0 when 1 then x_index = (width / 2) - recter.width / 2 when 2 then x_index = width - recter.width else raise "Text Cache : align is wrong" end return x_index end end #---------------------------------------------------------------------------- # ● New method: draw_cache_text #---------------------------------------------------------------------------- unless method_defined?(:draw_cache_text) def draw_cache_text(x, y, width, height, text, align = 0) blt_cache(x, y, width, height, text, align, false) end end #---------------------------------------------------------------------------- # ● New method: draw_edging_cache_text #---------------------------------------------------------------------------- unless method_defined?(:draw_edging_cache_text) def draw_edging_cache_text(x, y, width, height, text, align = 0) blt_cache(x, y, width, height, text, align, true) end end #---------------------------------------------------------------------------- # ● New method: draw_easy_cache_text #---------------------------------------------------------------------------- unless method_defined?(:draw_easy_cache_text) def draw_easy_cache_text(x, y, text) t_rect = text_size(text) blt_cache(x, y, t_rect.width, t_rect.height, text, 0, false) end end #---------------------------------------------------------------------------- # ● New method: draw_easy_edging_cache_text #---------------------------------------------------------------------------- unless method_defined?(:draw_easy_edging_cache_text) def draw_easy_edging_cache_text(x, y, text) t_rect = text_size(text) blt_cache(x, y, t_rect.width, t_rect.height, text, 0, true) end end #-------------------------------------------------------------------------- # * New method: change_color #-------------------------------------------------------------------------- unless method_defined?(:change_color) def change_color(color, enabled = true) font.color = color font.color.alpha = translucent_alpha unless enabled end end #-------------------------------------------------------------------------- # ● New method: draw_picture #-------------------------------------------------------------------------- unless method_defined?(:draw_picture) def draw_picture(file_name, x, y, opacity = 255) bitmap = LiTTleDRAgo.cache.picture(file_name) cw = bitmap.width ch = bitmap.height src_rect = Rect.new(0, 0, cw, ch) blt(x, y, bitmap, src_rect, opacity) end end #-------------------------------------------------------------------------- # ● New method: draw_icon #-------------------------------------------------------------------------- unless method_defined?(:draw_icon) def draw_icon(file_name, x, y, enabled = true) if file_name.is_a?(Numeric) bitmap = LiTTleDRAgo.cache.system("Iconset") src_rect = Rect.new(file_name % 16 * 24, file_name / 16 * 24, 24, 24) blt(x, y, bitmap, src_rect, enabled ? 255 : 160) elsif file_name.is_a?(String) bitmap = LiTTleDRAgo.cache.icon(file_name) src_rect = Rect.new(0, 0, 24, 24) blt(x, y, bitmap, bitmap.rect, enabled ? 255 : 160) end end end #-------------------------------------------------------------------------- # ● New method: draw_battler #-------------------------------------------------------------------------- unless method_defined?(:draw_battler) def draw_battler(file_name, x, y, hue = 0, enabled = true) bitmap = LiTTleDRAgo.cache.battler(file_name, hue) cw = bitmap.width ch = bitmap.height src_rect = Rect.new(0, 0, cw, ch) blt(x, y, bitmap, src_rect, enabled ? 255 : 160) end end #-------------------------------------------------------------------------- # ● New method: draw_bar #-------------------------------------------------------------------------- unless method_defined?(:draw_bar) def draw_bar(x, y, current, file) bitmap = LiTTleDRAgo.cache.picture(file) cw = bitmap.width * current / 100 ch = bitmap.height src_rect = Rect.new(0, 0, cw, ch) blt(x, y, bitmap, src_rect) end end #-------------------------------------------------------------------------- # ● New method: draw_edging_text #-------------------------------------------------------------------------- unless method_defined?(:draw_edging_text) def draw_edging_text(x, y, width, height, text, align=0) old_color = font.color.dup font.color = Color.new(0, 0, 0) draw_text(x-1, y-1, width, height, text, align) draw_text(x-1, y+1, width, height, text, align) draw_text(x+1, y-1, width, height, text, align) draw_text(x+1, y+1, width, height, text, align) font.color = old_color draw_text(x, y, width, height, text, align) end end #-------------------------------------------------------------------------- # ● New method: draw_enter_text #-------------------------------------------------------------------------- unless method_defined?(:draw_enter_text) def draw_enter_text(x, y, width, height, text, align=0) rect = text_size(text) info_box = text.split(/\n/) info_box.size.times do |i| draw_text( x, y+i*rect.height, width, height, info_box[i], align) break if (y+i*rect.height) > self.height end end end #-------------------------------------------------------------------------- # ● New method: draw_enter_edging_text #-------------------------------------------------------------------------- unless method_defined?(:draw_enter_edging_text) def draw_enter_edging_text(x, y, width, height, text, align=0) rect = text_size(text) info_box = text.split(/\n/) info_box.size.times do |i| draw_edging_text( x, y+i*rect.height,width,height,info_box[i],align) break if (y+i*rect.height) > self.height end end end #-------------------------------------------------------------------------- # ● New method: draw_easy_text #-------------------------------------------------------------------------- unless method_defined?(:draw_easy_text) def draw_easy_text(x, y, text) rect = text_size(text) draw_text(x, y, rect.width + rect.height/2, rect.height, text) end end #-------------------------------------------------------------------------- # ● New method: draw_auto_text #-------------------------------------------------------------------------- unless method_defined?(:draw_auto_text) def draw_auto_text(x, y, width, height, text) ini_x = 0 law = 0 text_box = [] text_box[law] = [] otxto = text.split(//) otxto.size.times do |i| text_rect = text_size(otxto[i]) if (x + ini_x + text_rect.width) < width ini_x += text_rect.width else law += 1 ini_x = text_rect.width text_box[law] = [] end text_box[law].push(otxto[i]) end for l in 0..law ini_x = 0 text_box[l].size.times do |i| rect = text_size(text_box[l][i]) draw_text(x + ini_x, y+l*height, rect.width, height, text_box[l][i]) ini_x += rect.width end end end end #------------------------------------------------------------------------- # ● New method: erase #------------------------------------------------------------------------- unless method_defined?(:erase) def erase(*a) rect = nil if a.at(0).is_a?(Rect) then rect = *a elsif a.size == 4 then rect = Rect.new(*a) elsif a.size == 0 then rect = Rect.new(0,0,width,height) end fill_rect(rect.x, rect.y, rect.width, rect.height, Color.erase) if rect end end #------------------------------------------------------------------------- # ● New method: stretch #------------------------------------------------------------------------- unless method_defined?(:stretch) def stretch(width, height) dummy = Bitmap.new(width, height) dummy.stretch_blt(*[dummy.rect, self, self.rect]) dummy end end #------------------------------------------------------------------------- # ● New method: crop #------------------------------------------------------------------------- unless method_defined?(:crop) def crop(*a) return unless a.size == 1 or a.size == 4 rect = rect.at(0) if a.size == 1 && a.at(0).is_a?(Rect) rect = Rect.new(*a) if a.size == 4 cropped = Bitmap.new([rect.width,width-rect.x].min, [rect.height,height-rect.y].min) cropped.blt(0,0,self,rect) cropped end end #------------------------------------------------------------------------- # ● Aliased method: stretch_blt #------------------------------------------------------------------------- def stretch_blt(*a) if respond_to?(:stretch_blend_blt) a = [a[0..2],0,1,a.at(3)||255].flatten stretch_blend_blt(*a) else drg_ce_stretch_blt(*a) end end #------------------------------------------------------------------------- # ● Aliased method: hue_change #------------------------------------------------------------------------- define_method(:hue_change) {|*args| [drg_ce_hue_change(*args)] && self } #---------------------------------------------------------------------------- # ● New method: invert #---------------------------------------------------------------------------- [:invert, :brighten, :darken, :grayscale, :pixelate, :frost, :flip_horizontal, :flip_vertical].each do |meth| define_sec_method(meth) do |*args| bitmap = self.clone bitmap.send(:"#{meth}!",*args) return bitmap end end #------------------------------------------------------------------------- # ● New method: flip_horizontal! #------------------------------------------------------------------------- unless method_defined?(:flip_horizontal!) def flip_horizontal! flipped = Bitmap.new(width, height) flip_rect = Rect.new(0, 0, 1, height) width.times do |i| flip_rect.x = width - 1 - i flipped.blt(i, 0, self, flip_rect) end clear blt(0, 0, flipped, rect) flipped.dispose end end #------------------------------------------------------------------------- # ● New method: flip_vertical! #------------------------------------------------------------------------- unless method_defined?(:flip_vertical!) def flip_vertical! len = width * height * 4 lenln = width * 4 pBuf = LiTTleDRAgo.malloc.call(len) src = address + len - lenln dst = pBuf height.times do |i| RtlMoveMemory_ip.call(dst,src,lenln) (src -= lenln) && (dst += lenln) end RtlMoveMemory_ip.call(address,pBuf,len) LiTTleDRAgo.free.call(pBuf) end end #---------------------------------------------------------------------------- # ● New method: invert! #---------------------------------------------------------------------------- unless method_defined?(:invert!) def invert! width.times do |i| height.times do |j| color = get_pixel(i, j) set_pixel(i, j, color.invert) if color.alpha > 0 end end end end #-------------------------------------------------------------------------- # * New method: brighten! #-------------------------------------------------------------------------- unless method_defined?(:brighten!) def brighten!(amount = 10) width.times do |w| height.times do |h| color = get_pixel(w, h) set_pixel(w, h, Color.new([color.red + amount, 255].min, [color.green + amount, 255].min, [color.blue + amount, 255].min, color.alpha)) if color.alpha > 0 end end end end #-------------------------------------------------------------------------- # * New method: darken! #-------------------------------------------------------------------------- unless method_defined?(:darken!) def darken!(amount = 10) width.times do |w| height.times do |h| color = get_pixel(w, h) set_pixel(w, h, Color.new([color.red - amount, 0].max, [color.green - amount, 0].max, [color.blue - amount, 0].max, color.alpha)) if color.alpha > 0 end end end end #-------------------------------------------------------------------------- # * New method: grayscale! # NOTE: calling this method repeatedly has no effect on the bitmap, but will # still waste processing power. Do not call it repeatedly. #-------------------------------------------------------------------------- unless method_defined?(:grayscale!) def grayscale! width.times do |w| height.times do |h| color = get_pixel(w, h) if (a = color.alpha) > 0 num = (color.red + color.green + color.blue) / 3 set_pixel(w, h, Color.new(num, num, num, a)) end end end end end #-------------------------------------------------------------------------- # * New method: drg_pixelate! (0.2 second) # NOTE: Pixelateing bitmaps to a larger pixel size is less process consuming. # for best results, don't pixelate to numbers below four. # This works much better for solid images, due to bugs. #-------------------------------------------------------------------------- unless method_defined?(:drg_pixelate!) def drg_pixelate!(size = 10) return self if size <= 1 c = lambda {|a,b| (a / b**2) * Math.sqrt(b) } for w in 0..((width - 1) / size) w *= size for h in 0..((height - 1) / size) h *= size r, g, b, a = 0, 0, 0, 0 size.times do |i| color = get_pixel(w, h) r += color.red g += color.green b += color.blue a += color.alpha color = get_pixel(w + i, h) r += color.red g += color.green b += color.blue a += color.alpha color = get_pixel(w, h + i) r += color.red g += color.green b += color.blue a += color.alpha end fill_rect(w, h, size, size, Color.new(c.call(r,size),c.call(g,size), c.call(b,size),c.call(a,size))) end end end end #-------------------------------------------------------------------------- # * New method: pixelate! #-------------------------------------------------------------------------- unless method_defined?(:pixelate!) def pixelate!(size = 10) return mosaic!(size,size) if respond_to?(:mosaic!) return drg_pixelate!(size) end end #-------------------------------------------------------------------------- # * New method: drg_frost! (5 second) # NOTE: Frosting a bitmap randomly scatters its pixels. As such, Consistant # results are impossible to get. # Frosting a bitmap beyond eight won't result in a more scattered image #-------------------------------------------------------------------------- unless method_defined?(:drg_frost!) def drg_frost!(noise = 10) for pass in 1..noise width.times do |w| height.times do |h| set_pixel(w, h, get_pixel(w + rand(3) - 1, h + rand(3) - 1)) end end end end end #------------------------------------------------------------------------- # ● New method: bltapiinit #------------------------------------------------------------------------- unless method_defined?(:bltapiinit) def bltapiinit info = [40,width,height,1,32,0,0,0,0,0,0].pack('LllSSLLllLL') hWndDC = LiTTleDRAgo.getdc.call(LiTTleDRAgo.hwnd) hMemDC = LiTTleDRAgo.ccdc.call(hWndDC) hMemBM = LiTTleDRAgo.ccbitmap.call(hWndDC, width, height) LiTTleDRAgo.releasedc.call(LiTTleDRAgo.hwnd, hWndDC) LiTTleDRAgo.selectobject.call(hMemDC, hMemBM) LiTTleDRAgo.setdibits.call(hMemDC, hMemBM, 0, height, address, info, 0) return hMemDC, hMemBM, info end end #------------------------------------------------------------------------- # ● New method: bit_blt #------------------------------------------------------------------------- unless method_defined?(:bit_blt) def bit_blt(x, y, src_bmp, src_rect, rastor_operation = 0xCC0020) hDC1, hBM1, info = *self.bltapiinit hDC2, hBM2 = *src_bmp.bltapiinit LiTTleDRAgo.bitblt.call(hDC1, x, y, src_rect.width, src_rect.height, hDC2, src_rect.x, src_rect.y, rastor_operation) LiTTleDRAgo.getdibits.call(hDC1, hBM1, 0, height, address, info, 0) LiTTleDRAgo.deleteobject.call(hBM1) LiTTleDRAgo.deleteobject.call(hDC1) LiTTleDRAgo.deleteobject.call(hBM2) LiTTleDRAgo.deleteobject.call(hDC2) end end #------------------------------------------------------------------------- # ● New method: crop_blt #------------------------------------------------------------------------- unless method_defined?(:crop_blt) def crop_blt(x, y, width, height, bitmap, dir = 1, align = 1, opacity = 255) w, h = bitmap.width, bitmap.height if w < width and h < height x += (width - w) / 2 if align == 1 x += width - w if align == 2 return full_blt(x, y, bitmap, opacity) end i, j = dir % 3, dir / 3 crop_x, crop_y = 0, 0 crop_x = (w - width) / 2 if i == 1 crop_x = w - width if i == 2 crop_y = (h - height) / 2 if j == 1 crop_y = h - height if j == 2 blt(x, y, bitmap, Rect.new(crop_x, crop_y, width, height), opacity) end end #------------------------------------------------------------------------- # ● New method: fit_blt #------------------------------------------------------------------------- unless method_defined?(:fit_blt) def fit_blt(x, y, width, height, bitmap, opacity = 255, align = 1) w, h = bitmap.width, bitmap.height if w > width or h > height conversion = w / h.to_f zoom_x, zoom_y = width * conversion, height if conversion <= 1 zoom_x, zoom_y = width, height / conversion unless conversion <= 1 x += (width - zoom_x) / 2 if align == 1 x += width - zoom_x if align == 2 dest_rect = Rect.new(x, y, zoom_x, zoom_y) stretch_blt(dest_rect, bitmap, bitmap.rect, opacity) else x += (width - w) / 2 if align == 1 x += width - w if align == 2 full_blt(x, y, bitmap, opacity) end end end #------------------------------------------------------------------------- # ● New method: full_blt #------------------------------------------------------------------------- unless method_defined?(:full_blt) def full_blt(x, y, bitmap, opacity = 255) blt(x, y, bitmap, bitmap.rect, opacity) end end #------------------------------------------------------------------------- # ● New method: scale_blt #------------------------------------------------------------------------- unless method_defined?(:scale_blt) def scale_blt(dest_rect, src_bitmap, src_rect = src_bitmap.rect, o = 255) w, h = src_rect.width, src_rect.height scale = [w / dest_rect.width.to_f, h / dest_rect.height.to_f].max ow, oh = (w / scale).to_i, (h / scale).to_i ox, oy = (dest_rect.width - ow) / 2, (dest_rect.height - oh) / 2 stretch_blt(Rect.new(ox + dest_rect.x, oy + dest_rect.y, ow, oh), src_bitmap, src_rect, o) end end #------------------------------------------------------------------------- # ● New method: frames_flip_horizontal #------------------------------------------------------------------------- unless method_defined?(:frames_flip_horizontal) def frames_flip_horizontal(frames) frame_width = width / frames frame_bitmap = Bitmap.new(frame_width, height) rect = Rect.new(0, 0, frame_width, height) frames.times do |i| frame_bitmap.clear x = i * frame_width rect.x = x frame_bitmap.blt(0, 0, self, rect) frame_bitmap.flip_horizontal! blt(x, 0, frame_bitmap, frame_bitmap.rect) end frame_bitmap.dispose end end #------------------------------------------------------------------------- # ● New method: frames_flip_vertical #------------------------------------------------------------------------- unless method_defined?(:frames_flip_vertical) def frames_flip_vertical(frames) frame_height = height / frames frame_bitmap = Bitmap.new(width, frame_height) rect = Rect.new(0, 0, width, frame_height) frames.times do |i| frame_bitmap.clear y = i * frame_height rect.y = y frame_bitmap.blt(0, 0, self, rect) frame_bitmap.flip_vertical! blt(0, y, frame_bitmap, frame_bitmap.rect) end frame_bitmap.dispose end end #------------------------------------------------------------------------- # ● New method: blur_area #------------------------------------------------------------------------- unless method_defined?(:blur_area) def blur_area(settings = {}) blur_settings.each do |default, setting| settings[default] = setting unless settings.has_key?(default) end keys = settings.keys rect_defined = keys.include?('rect') rect_p_defined = keys.include?('x') && keys.include?('y') && keys.include?('w') && keys.include?('h') if rect_defined rect = settings['rect'] x, y, w, h = rect.x, rect.y, rect.width, rect.height elsif rect_p_defined x, y, w, h = settings['x'], settings['y'], settings['w'], settings['h'] else x, y, w, h = 0, 0, self.width, self.height end dummy = self.dup spacing = settings['spacing'] opacity = settings['opacity'] settings['offset'].times do |i| src_rects = [] src_rects << Rect.new(x + i * spacing, y + i * spacing, w, h) src_rects << Rect.new(x - i * spacing, y + i * spacing, w, h) src_rects << Rect.new(x + i * spacing, y - i * spacing, w, h) src_rects << Rect.new(x - i * spacing, y - i * spacing, w, h) o = Integer(opacity * (settings['offset'] - i) / (settings['offset'])) src_rects.each { |src_rect| blt(x, y, dummy, src_rect, o)} end dummy.dispose self end end #------------------------------------------------------------------------- # ● New method: sub_bitmap_blend #------------------------------------------------------------------------- unless method_defined?(:sub_bitmap_blend) def sub_bitmap_blend(x = 0, y = 0, bitmap = self, src_rect = bitmap.rect) src_rect.width.times do |i| src_rect.height.times do |j| c1 = get_pixel(x + i, y + j) c2 = bitmap.get_pixel(src_rect.x + i, src_rect.y + j) nc = Color.new(c1.red-c2.red, c1.green-c2.green, c1.blue-c2.blue) set_pixel(x + i, y + j, nc) if c2.alpha > 0 end end end end #------------------------------------------------------------------------- # ● New method: add_bitmap_blend #------------------------------------------------------------------------- unless method_defined?(:add_bitmap_blend) def add_bitmap_blend(x = 0, y = 0, bitmap = self, src_rect = bitmap.rect) src_rect.width.times do |i| src_rect.height.times do |j| c1 = get_pixel(x + i, y + j) c2 = bitmap.get_pixel(src_rect.x + i, src_rect.y + j) nc = Color.new(c1.red+c2.red, c1.green+c2.green, c1.blue+c2.blue) set_pixel(x + i, y + j, nc) if c2.alpha > 0 end end end end #-------------------------------------------------------------------------- # * Alias Listing #-------------------------------------------------------------------------- alias_sec_method :frost!, :drg_frost! alias_sec_method :blur, :blur_area alias_sec_method :entire_fill, :full_fill #-------------------------------------------------------------------------- # * Replicated method: gradient_fill_rect #-------------------------------------------------------------------------- unless method_defined?(:gradient_fill_rect) def gradient_fill_rect(*a) if a.first.is_a?(Rect) x, y, width, height = a[0].x, a[0].y, a[0].width, a[0].height color1 = a.at(1).dup color2 = a.at(2) vertical = a.at(3) else x, y, width, height = a[0..3] color1 = a.at(4).dup color2 = a.at(5) vertical = a.at(6) end dr = color2.red - color1.red dg = color2.green - color1.green db = color2.blue - color1.blue da = color2.alpha - color1.alpha start_rgba = [color1.red, color1.green, color1.blue, color1.alpha] if vertical dr, dg, db, da = dr / height, dg / height, db / height, da / height for i in (y.round...(y + height).round) fill_rect(x, i, width, 1, color1) start_rgba[0] = [start_rgba.at(0) + dr, 0].max.round start_rgba[1] = [start_rgba.at(1) + dg, 0].max.round start_rgba[2] = [start_rgba.at(2) + db, 0].max.round start_rgba[3] = [start_rgba.at(3) + da, 0].max.round color1.set(*start_rgba) end else dr, dg, db, da = dr / width, dg / width, db / width, da / width for i in (x.round...(x + width).round) fill_rect(i, y, 1, height, color1) start_rgba[0] = [start_rgba.at(0) + dr, 0].max.round start_rgba[1] = [start_rgba.at(1) + dg, 0].max.round start_rgba[2] = [start_rgba.at(2) + db, 0].max.round start_rgba[3] = [start_rgba.at(3) + da, 0].max.round color1.set(*start_rgba) end end end end end #============================================================================== # ** Range #------------------------------------------------------------------------------ # #============================================================================== class Range #-------------------------------------------------------------------------- # * Include Comparable #-------------------------------------------------------------------------- include(Comparable) #------------------------------------------------------------------------- # ● New method: random #------------------------------------------------------------------------- define_sec_method(:random) { self.to_a.random } #------------------------------------------------------------------------- # ● New method: <=> #------------------------------------------------------------------------- unless method_defined?(:"<=>") def <=>(other) temp = first <=> other.first temp = last <=> other.last if temp = 0 return temp end end end #============================================================================== # ** String #------------------------------------------------------------------------------ # #============================================================================== class String #------------------------------------------------------------------------- # ● New method: get_int #------------------------------------------------------------------------- unless method_defined?(:get_int) def get_int m = self.scan(/([-]?\d+)/i).flatten return m.join.to_i end end #------------------------------------------------------------------------- # ● New method: get_ints #------------------------------------------------------------------------- unless method_defined?(:get_ints) def get_ints array = self.scan(/([-]?\d+)/i).flatten.relay(:i) return array end end #------------------------------------------------------------------------- # ● New method: encrypt #------------------------------------------------------------------------- unless method_defined?(:encrypt) def encrypt(encryption_string = 'encrypt') encryption_bytes = [] encryption_string.each_byte {|c| encryption_bytes << c} string = '' self.size.times do |i| byte = self[i] * encryption_bytes[i % encryption_bytes.size] base, mod = byte / 255, byte % 255 string += base.chr + mod.chr end return string end end #------------------------------------------------------------------------- # ● New method: encrypt! #------------------------------------------------------------------------- unless method_defined?(:encrypt!) def encrypt!(encryption_string = 'encrypt') replace(encrypt(encryption_string)) end end #------------------------------------------------------------------------- # ● New method: decrypt #------------------------------------------------------------------------- unless method_defined?(:decrypt) def decrypt(encryption_string = 'encrypt') encryption_bytes = [] encryption_string.each_byte {|c| encryption_bytes << c} string = '' (self.size / 2).times do |i| b, m = self[i * 2] * 255, self[i * 2 + 1] string += ((b + m) / encryption_bytes[i % encryption_bytes.size]).chr end return string end end #------------------------------------------------------------------------- # ● New method: decrypt! #------------------------------------------------------------------------- unless method_defined?(:decrypt!) def decrypt!(encryption_string = 'encrypt') replace(decrypt(encryption_string)) end end #------------------------------------------------------------------------- # ● New method: clear, words, characters #------------------------------------------------------------------------- define_sec_method(:clear) { replace('') } define_sec_method(:words) { split(' ') } define_sec_method(:characters) { split('') } define_sec_method(:last) { characters.last } define_sec_method(:first) { characters.first } end #============================================================================== # ** Game_Interpreter #------------------------------------------------------------------------------ # An interpreter for executing event commands. This class is used within the # Game_Map, Game_Troop, and Game_Event classes. #============================================================================== Klass = LiTTleDRAgo::VX ? Game_Interpreter : Interpreter class Klass #-------------------------------------------------------------------------- # * Include InterpreterScriptCalls #-------------------------------------------------------------------------- include(InterpreterScriptCalls) #-------------------------------------------------------------------------- # * Constant #-------------------------------------------------------------------------- SCRIPT_WAIT_RESULTS = [:wait, FalseClass] #-------------------------------------------------------------------------- # ● Redirect Listing #-------------------------------------------------------------------------- redirect_method :picture_sprite, '$game_map.picture_sprite' #-------------------------------------------------------------------------- # ● New method: random_teleport #-------------------------------------------------------------------------- unless method_defined?(:random_teleport) def random_teleport(id = 0) character = id.is_a?(Game_Character) ? id : get_character(id) character.random_teleport if character.is_a?(Game_Character) end end #-------------------------------------------------------------------------- # ● Redefined method: same_map?, next_event_code #-------------------------------------------------------------------------- define_sec_method(:same_map?) { @map_id == $game_map.map_id } define_sec_method(:next_event_code) { @list[@index + 1].code } #-------------------------------------------------------------------------- # * Overwriten method: command_355 #-------------------------------------------------------------------------- def command_355 script = @list[index = @index].parameters[0] + "\n" while [655, 355].include?(next_event_code) do script += @list[@index+=1].parameters[0] + "\n" end #script.gsub!(/(\w+)\s*\n\s*[\n]*?\s*.\s*[\n]*?\s*(\w+)/i){"#{$1}.#{$2}"} #script.gsub!(/(["'])\s*\n\s*[\n]*?\s*(["'])/i) {"#{$1}+#{$2}"} wait = SCRIPT_WAIT_RESULTS.include?(eval(script)) && LiTTleDRAgo::XP return wait ? !(@index = index) : true end end #============================================================================== # ** Sprite #------------------------------------------------------------------------------ # A sprite class for bitmap processing. #============================================================================== class Sprite #--------------------------------------------------------------------------- # * Alias Listing #--------------------------------------------------------------------------- alias_sec_method :angle_quaternion_fix_alias, :"angle=" #--------------------------------------------------------------------------- # * New method: method_missing #--------------------------------------------------------------------------- def method_missing(val,*a,&b) return bitmap.send(val.to_s,*a,&b) if bitmap.respond_to?(val.to_sym) text = "Undefined method #{val} at #{self.inspect}" raise(NoMethodError, text, caller(1)) end #--------------------------------------------------------------------------- # * Aliased method: angle= #--------------------------------------------------------------------------- def angle=(val) if @angle != val (@angle = val) && (val % 360 == 180 || val % 180 == 90) && val *= 1.00001 angle_quaternion_fix_alias(val) end end #-------------------------------------------------------------------------- # ● New method: sclone #-------------------------------------------------------------------------- unless method_defined?(:sdup) def sclone sprite = Sprite.new(self.viewport) sprite.bitmap = self.bitmap.clone sprite.zoom_x, sprite.zoom_y = self.zoom_x, self.zoom_y sprite.x, sprite.y = self.x, self.y sprite.ox, sprite.oy = self.ox, self.oy sprite.color, sprite.tone = self.color.dup, self.tone.dup sprite.src_rect = self.src_rect sprite.angle = self.angle return sprite end alias_method :sdup, :sclone end #-------------------------------------------------------------------------- # ● New method: scale #-------------------------------------------------------------------------- unless method_defined?(:scale) def scale(w, h) tmp = self.bitmap.clone self.bitmap = Bitmap.new(w, h) self.bitmap.stretch_blt(Rect.new(0, 0, w, h), tmp, tmp.rect) tmp.dispose end end #-------------------------------------------------------------------------- # ● New method: in_rect? #-------------------------------------------------------------------------- unless method_defined?(:in_rect?) def in_rect?(*rect) if rect.size == 1 rect = rect[0] return (self.x.between?(rect.x, rect.x + rect.width) && self.y.between?(rect.y, rect.y + rect.height)) elsif rect.size == 4 x, y, width, height = rect return self.x.between?(x, x + width) && self.y.between?(y, y + height) end return false end end #-------------------------------------------------------------------------- # ● Overwriten method: clone & dup #-------------------------------------------------------------------------- define_method(:clone) {|*a| sclone } define_method(:dup) {|*a| sdup } end #============================================================================== # ** Scheduler #------------------------------------------------------------------------------ # This class allows to schedule a proc or method call a given amount of frames # into the future with any amount of arguments #============================================================================== class Scheduler #============================================================================ # ** Order #---------------------------------------------------------------------------- # An order is a proc, method or something else which has 'call' as a method, # and the arguments to pass along. #============================================================================ unless method_defined?(:update) Order = Struct.new(:callable, :arguments) class Order #------------------------------------------------------------------------ # * New Methods: call #------------------------------------------------------------------------ define_method(:call) { callable.call(*arguments) } end #========================================================================== # ** RecurringOrder #-------------------------------------------------------------------------- # An order which is recurring every specified amount of time until # FalseClass is returned from the call. # Note that arguments remain the same for each call #========================================================================== RecurringOrder = Struct.new(:callable, :arguments, :frames) class RecurringOrder #------------------------------------------------------------------------ # * New Methods: call #------------------------------------------------------------------------ def call result = callable.call(*arguments) unless result == FalseClass Scheduler.schedule_recurring(frames, frames, callable, *arguments) end end end #========================================================================== # ** Mapping #-------------------------------------------------------------------------- # Maps an index to an array. Values can be added to these value. # Each array starts empty. #========================================================================== class Mapping #------------------------------------------------------------------------ # * New method: add, get, empty #------------------------------------------------------------------------ define_method(:add) { |i, v| ((@mapping ||= {})[i] ||=[]) << v } define_method(:get) { |i| ((@mapping ||= {})[i] || []) } define_method(:empty) { |i| (@mapping ||= {}).delete(i) } end #-------------------------------------------------------------------------- # * New method: schedule #-------------------------------------------------------------------------- def schedule(frames, callable, *arguments) order = Order.new(callable, arguments) (@mapping ||= Mapping.new).add(frames + (@tick||=0), order) end #-------------------------------------------------------------------------- # * New method: schedule_recurring #-------------------------------------------------------------------------- def schedule_recurring(frames, frames_to_wait, callable, *arguments) order = RecurringOrder.new(callable, arguments, frames_to_wait) (@mapping ||= Mapping.new).add(frames + (@tick||=0), order) end #-------------------------------------------------------------------------- # * New method: update #-------------------------------------------------------------------------- def update orders = (@mapping ||= Mapping.new).get((@tick||=0)) @mapping.empty(@tick) orders.each {|s| s.call } @tick += 1 end #-------------------------------------------------------------------------- # * Self #-------------------------------------------------------------------------- @@instance = self.new class << self define_method(:instance) { @@instance } redirect_method :schedule_recurring, 'instance.schedule_recurring' redirect_method :schedule, 'instance.schedule' redirect_method :update, 'instance.update' end end end #============================================================================== # ** Dir #------------------------------------------------------------------------------ # #============================================================================== class Dir #------------------------------------------------------------------------- # * Self #------------------------------------------------------------------------- class << self #-------------------------------------------------------------------------- # ● New method: make_dir #-------------------------------------------------------------------------- unless method_defined?(:make_dir) def make_dir(path) dir = path.split("/") dir.size.times do |i| unless dir == "." add_dir = dir[0..i].join("/") begin Dir.mkdir(add_dir) rescue end end end end end end end #============================================================================== # ** BitmapDump #------------------------------------------------------------------------------ # #============================================================================== module BitmapDump #-------------------------------------------------------------------------- # * Directory #-------------------------------------------------------------------------- Directory = 'Graphics/Saved Images/' #------------------------------------------------------------------------- # * Self #------------------------------------------------------------------------- class << self #-------------------------------------------------------------------------- # ● New method: self.bitmap_data #-------------------------------------------------------------------------- unless method_defined?(:bitmap_data) def bitmap_data(bitmap) red = Table.new(bitmap.width, bitmap.height) green = red.clone blue = red.clone alpha = red.clone bitmap.width.times do |i| bitmap.height.times do |j| color = bitmap.get_pixel(i, j) red[i, j] = color.red green[i, j] = color.green blue[i, j] = color.blue alpha[i, j] = color.alpha end end return [red, green, blue, alpha] end end #-------------------------------------------------------------------------- # ● New method: self.read_bitmap_data #-------------------------------------------------------------------------- unless method_defined?(:read_bitmap_data) def read_bitmap_data(red, green, blue, alpha) bitmap = Bitmap.new(red.xsize, red.ysize) bitmap.width.times do |i| bitmap.height.times do |j| color_table = [red[i, j], green[i, j], blue[i, j], alpha[i, j]] bitmap.set_pixel(i, j, Color.new(*color_table)) end end return bitmap end end #-------------------------------------------------------------------------- # ● New method: self.save_bitmap #-------------------------------------------------------------------------- unless method_defined?(:save_bitmap) def save_bitmap(bitmap, filename) bitmap_data = bitmap_data(bitmap) Dir.make_dir(Directory) unless FileTest.directory?(Directory) path = "#{Directory}/#{filename}.#{self.data_default_extension}" file = File.open(path,'wb') Marshal.dump(bitmap_data, file) file.close end end #-------------------------------------------------------------------------- # ● New method: self.load_bitmap #-------------------------------------------------------------------------- unless method_defined?(:load_bitmap) def load_bitmap(filename) Dir.make_dir(Directory) unless FileTest.directory?(Directory) path = "#{Directory}/#{filename}.#{self.data_default_extension}" file = File.open(path,"rb") colors = Marshal.load(file) file.close red, green, blue, alpha = colors[0], colors[1], colors[2], colors[3] bitmap = read_bitmap_data(red, green, blue, alpha) return bitmap end end #-------------------------------------------------------------------------- # ● New method: self.data_default_extension #-------------------------------------------------------------------------- unless method_defined?(:data_default_extension) def data_default_extension $game_map ||= Game_Map.new $game_map.data_default_extension end end end end $imported[:drg_replicated_fiber] = 1.01 #============================================================================== # ** Fiber #------------------------------------------------------------------------------ # #============================================================================== unless defined?(Fiber) class Fiber #------------------------------------------------------------------------- # * New method: initialize #------------------------------------------------------------------------- def initialize block_given? || raise(ArgumentError,'new Fiber requires a block') @yield = Queue.new @resume = Queue.new @thread = Thread.new { @yield.push [yield(*@resume.pop)] } @thread.abort_on_exception = true @thread[:fiber] = self end #------------------------------------------------------------------------- # * New method: self.current #------------------------------------------------------------------------- def self.current Thread.current[:fiber] || raise(FiberError,'not inside a fiber',caller(1)) end #------------------------------------------------------------------------- # * New method: self.yield #------------------------------------------------------------------------- def self.yield(*a) text = "can't yield from root fiber" (fiber = Thread.current[:fiber]) || raise(FiberError,text,caller(1)) fiber.yield(*a) end #------------------------------------------------------------------------- # * New method: inspect, alive? #------------------------------------------------------------------------- define_method(:inspect) { "#<#{self.class}:0x#{self.object_id.to_s(16)}>" } define_method(:alive?) { @thread.alive? } #------------------------------------------------------------------------- # * New method: resume #------------------------------------------------------------------------- def resume(*a) alive? || raise(FiberError,'dead fiber called',caller(1)) @resume.push(a) result = @yield.pop result.size > 1 ? result : result.first end #------------------------------------------------------------------------- # * New method: yield #------------------------------------------------------------------------- def yield(*a) @yield.push(a) result = @resume.pop result.size > 1 ? result : result.first end end end #============================================================================== # ** FiberError #------------------------------------------------------------------------------ # #============================================================================== defined?(FiberError) || (class FiberError < StandardError ; end) #============================================================================== # ** Queue #------------------------------------------------------------------------------ # #============================================================================== unless defined?(Queue) class Queue #------------------------------------------------------------------------- # * New method: initialize #------------------------------------------------------------------------- def initialize (@que ||= []).taint (@waiting ||= []).taint # enable tainted comunication self.taint end #------------------------------------------------------------------------- # * New method: clear, empty?, length, num_waiting #------------------------------------------------------------------------- define_method(:clear) { @que.clear } define_method(:empty?) { @que.empty? } define_method(:length) { @que.length } define_method(:num_waiting) { @waiting.size } #------------------------------------------------------------------------- # * New method: pop #------------------------------------------------------------------------- def pop(non_block=false) while (Thread.critical = true; @que.empty?) non_block && raise(ThreadError,"queue empty",caller(1)) @waiting.push(Thread.current) Thread.stop end @que.shift ensure Thread.critical = false end #------------------------------------------------------------------------- # * New method: push #------------------------------------------------------------------------- def push(obj) Thread.critical = true @que.push obj begin t = @waiting.shift t && t.wakeup rescue ThreadError retry ensure Thread.critical = false end begin t && t.run rescue ThreadError end end #------------------------------------------------------------------------- # * Alias Listing #------------------------------------------------------------------------- method_defined?(:size) || (alias_method :size, :length) method_defined?(:shift) || (alias_method :shift, :pop) method_defined?(:deq) || (alias_method :deq, :pop) method_defined?(:"<<") || (alias_method :"<<", :push) method_defined?(:enq) || (alias_method :enq, :push) end end