RMVX Game Patcher
Version 1.2.0
Introduction
You've just released your grand project. It has a compressed size of 142MB. You uploaded and posted it. Suddenly, you remembered you forgot something! Your starting place is in the wrong spot, and you didn't finish that event page! And what's this! Your first boss is way too hard! You want to fix it, but that 142MB upload took an hour! Thankfully, you remembered to install Yeyinde's VX Patch script! You quickly create a 25KB patch file and upload it. Now, with the patch you provided, the game runs just like it should. What would you do without it?
This script allows you to patch your game with various "Patch Files". These files can add scripts, change game data, and even add new features! Game patches are small in size, so they are easily uploaded. Patch files also have a security feature: Only "authorized" patches can be loaded into your game thanks to a "Master Password". Patch files that do not meet this password will close the game.
Patches: The easy way to fix and add.
Scripts
Instructions
Setting Up:
1) Change the KEY in the Patcher module. This is the password that lets only authorized patches work.
2) Change the DIR in the Patcher module if you want to use a different folder to get patches from.
3) Change the EXT in the Patcher module to have a different extension for patch files.
4) By rearranging SALT, even more security can be added!
Making a Patch:
1) Add scripts you want into a text file and give the file the extension ".rb". Save this file in your game's main directory. (OPTIONAL)
2) Call Script: $scene = Scene_PatchMaker.new
3) Select the script you want to use in the Script menu. (OPTIONAL IF DATA IS INCLUDED)
4) Select the data you want to include in your patch. Data is categorized, so it is easy to locate. The true/false in the top right corner indicates if the data will be in the patch file. (OPTIONAL IF SCRIPT IS INCLUDED)
5) Select ">FINISH". This will generate your patch file.
6) Rename your patch. The order in which the Game Patcher will load things is in this order: -, _, 0 to 9, A to Z, a-z. Patches that are loaded last can overwrite previously loaded patches.
7) Enjoy your small patch file.
Notes
Does not patch audio files.
VX->XP Conversion Fund
For those who really want this script in XP, please contribute to the $30 fund.
Funds: $0/30
Version 1.2.0
Introduction
You've just released your grand project. It has a compressed size of 142MB. You uploaded and posted it. Suddenly, you remembered you forgot something! Your starting place is in the wrong spot, and you didn't finish that event page! And what's this! Your first boss is way too hard! You want to fix it, but that 142MB upload took an hour! Thankfully, you remembered to install Yeyinde's VX Patch script! You quickly create a 25KB patch file and upload it. Now, with the patch you provided, the game runs just like it should. What would you do without it?
This script allows you to patch your game with various "Patch Files". These files can add scripts, change game data, and even add new features! Game patches are small in size, so they are easily uploaded. Patch files also have a security feature: Only "authorized" patches can be loaded into your game thanks to a "Master Password". Patch files that do not meet this password will close the game.
Patches: The easy way to fix and add.
Scripts
Code:
#==============================================================================
# ** Game Patcher
#------------------------------------------------------------------------------
# * Scripted by: Yeyinde
# * Version 1.2.0
# * Date: 03/08/08
#------------------------------------------------------------------------------
# This script lets you patch your game.
# In this version, scripts, data and graphics can be patched.
#------------------------------------------------------------------------------
module Patcher
EXT = '.rvdata'
KEY = 'MyPa5Sw0|2d'
DIR = 'Patch'
SALT = %w(a b c d e f g h i j k l m n o p q r s t u v w x y z .
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z /)
unless File.directory?(DIR)
Dir.mkdir(DIR)
end
end
class RPG::Map
alias original_init initialize
attr_accessor :id
def initialize
original_init
@id = 0
end
end
class RPG::MapInfo
alias original_init initialize
attr_accessor :id
def initialize
original_init
@id = 0
end
end
class Game_Map
def setup(map_id)
@map_id = map_id
@map = $data_maps[@map_id]
if @map.nil?
print "Map #{@map_id} could not be located."
exit
end
@display_x = 0
@display_y = 0
@passages = $data_system.passages
referesh_vehicles
setup_events
setup_scroll
setup_parallax
@need_refresh = false
end
end
class Font
def marshal_dump;end
def marshal_load(obj);end
end
class Bitmap
# メモリ転é€ç”¨ã®é–¢æ•°
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
def _dump(limit)
data = "rgba" * width * height
RtlMoveMemory_pi.call(data, address, data.length)
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*") # ã¤ã„ã§ã«åœ§ç¸®
end
def self._load(str)
w, h, zdata = str.unpack("LLa*"); b = new(w, h)
RtlMoveMemory_ip.call(b.address, Zlib::Inflate.inflate(zdata), w * h * 4); b
end
# [[[bitmap.object_id * 2 + 16] + 8] + 16] == 生データã®å…ˆé (注æ„:上下å転)
def address
buffer, ad = "xxxx", object_id * 2 + 16
RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 8
RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 16
RtlMoveMemory_pi.call(buffer, ad, 4); return buffer.unpack("L")[0]
end
end
module Cache
def self.set_bitmap(bitmap, path)
@cache = {} if @cache == nil
path = 'Graphics/' + path
if @cache[path]
@cache[path].dispose
@cache[path] = nil
end
@cache[path] = bitmap.clone
end
end
module Patcher
NEW_DATA = {}
CLASS_MAP = {RPG::Actor=>'$data_actors', RPG::Class=>'$data_classes',
RPG::Skill=>'$data_skills', RPG::Item=>'$data_items',
RPG::Weapon=>'$data_weapons', RPG::Armor=>'$data_armors',
RPG::Enemy=>'$data_enemies', RPG::Troop=>'$data_troops',
RPG::Animation=>'$data_animations', RPG::Map=>'$data_maps',
RPG::MapInfo=>'$data_mapinfos', RPG::State=>'$data_states',
RPG::CommonEvent=>'$data_common_events', RPG::System=>'$data_system',
RPG::Area=>'$data_areas'}
$data_mapinfos = load_data('Data/MapInfos.rvdata')
$data_maps = {}
(1..999).each do |map_id|
begin
map = load_data(sprintf("Data/Map%03d.rvdata", map_id))
map.id = map_id
$data_maps[map_id] = map
$data_mapinfos[map_id].id = map_id
rescue Errno::ENOENT
end
end
def self.patch_data
Patcher::NEW_DATA.each do |entry, data|
eval(entry + '=data')
end
end
def self.start_patcher
Dir[Patcher::DIR + '/*' + Patcher::EXT].sort.each do |path|
load_patch(path)
end
end
end
def load_patch(file_name)
key = ''
mtime = 0
patch_script = []
begin
file = Zlib::GzipReader.open(file_name)
key = file.comment
mtime = file.mtime.to_i
if file.orig_name != 'patch_data'
print "Unauthorized patch detected.\n(#{file_name})"
exit
end
patch_script = Marshal.load(file)
other_data = []
while !file.eof?
other_data << Marshal.load(file)
end
other_data.each do |data_entry|
if data_entry.is_a?(Array)
Cache.set_bitmap(data_entry[0], data_entry[1])
elsif !data_entry.is_a?(RPG::System)
Patcher::NEW_DATA[Patcher::CLASS_MAP[data_entry.class] + '[' +
data_entry.id.to_s + ']'] = data_entry
else
Patcher::NEW_DATA[Patcher::CLASS_MAP[data_entry.class]] = data_entry
end
end
file.close
salt = Patcher::SALT[mtime % 54] + Patcher::SALT[(mtime % 54) ^ 53]
if key != Patcher::KEY.crypt(salt)[2..-1]
print "Unauthorized patch detected.\n(#{file_name})"
exit
end
eval(Zlib::Inflate.inflate(patch_script))
rescue ScriptError, SyntaxError, TypeError
print "Unauthorized patch detected.\n(#{file_name})"
exit
end
end
class Scene_Title
alias patcher_database load_database
alias patcher_btdatabase load_bt_database
def load_database
patcher_database
Patcher.patch_data
end
def load_bt_database
patcher_btdatabase
Patcher.patch_data
end
end
Code:
class Window_DataSelect < Window_Command
 def initialize
  super(212, ['Script', 'Graphics'] + Patcher::CLASS_MAP.values.sort + ['>FINISH'])
  self.height = 32 + WLH * 17
  self.y = (Graphics.height - self.height) / 2
 end
 def selection
  return @commands[self.index]
 end
end
class Window_CurrentMode < Window_Base
 def initialize
  super(0, 0, 212, WLH+32)
 end
 def set(mode)
  return if @mode == mode
  self.contents.clear
  @mode = mode
  self.contents.draw_text(4, 0, 172, WLH, @mode)
 end
end
class Window_FileList < Window_Selectable
 attr_accessor :mode
 def initialize(array = [])
  super(0, 32+WLH, 212, WLH * 15+32)
  self.index = 0
  self.visible = false
  self.active = false
  @data = array
  @mode = 0
  refresh
 end
 def data(index = self.index)
  dat = nil
  if @data.is_a?(Array)
   dat = @data[self.index]
  else
   dat = @data[@data.keys[index]]
  end
  return dat
 end
 def data=(array)
  @data = array.dup
  refresh
 end
 def refresh
  self.index = 0
  if @mode == 0
   @data << nil
  else
   @data.compact! if @data.is_a?(Array)
  end
  @item_max = @data.size
  create_contents
  for i in 0...@item_max
   draw_item(i)
  end
 end
 def draw_item(index)
  if data(index).is_a?(RPG::Map) || data(index).is_a?(RPG::MapInfo)
   self.contents.draw_text(item_rect(index), 'Map ' + data(index).id.to_s)
  elsif data(index).is_a?(RPG::Area)
   self.contents.draw_text(item_rect(index), 'Area ' + data(index).id.to_s)
  elsif @data[index].is_a?(String)
   self.contents.draw_text(item_rect(index), @data[index])
  elsif @data[index].nil?
   self.contents.draw_text(item_rect(index), 'Use No Script')
  else
   self.contents.draw_text(item_rect(index), 'Data ' + (index + 1).to_s)
  end
 end
end
class Window_DataInfo < Window_Base
 def initialize
  super(212, 0, 332, WLH*17+32)
  self.y = (Graphics.height - self.height) / 2
  self.visible = false
  @data = nil
  @using = false
 end
 def set_data(data, using = false)
  return if (@data == data && @using == using)
  self.contents.clear
  @data = data
  @using = using
  if data
   branch_per_class(data)
   self.contents.draw_text(4, 0, 292, WLH, data.class.to_s)
   self.contents.draw_text(4, 0, 292, WLH, using, 2)
  else
   self.contents.draw_text(4, 0, 292, WLH, 'No custom data')
  end
 end
 def branch_per_class(object)
  case object
  when String
   return unless @data.include?('/')
   bitmap = Cache.load_bitmap('Graphics/' + @data.split('/')[0] + '/',
    @data.split('/')[1])
   self.contents.blt(0, 0, bitmap, bitmap.rect)
  when RPG::Actor
   draw_actor
  when RPG::Animation
   draw_animation
  when RPG::Area
   draw_area
  when RPG::Armor
   draw_armor
  when RPG::Class
   draw_class
  when RPG::CommonEvent
   draw_common_event
  when RPG::Enemy
   draw_enemy
  when RPG::Item
   draw_item
  when RPG::MapInfo
   draw_mapinfo
  when RPG::Map
   draw_map
  when RPG::Skill
   draw_skill
  when RPG::State
   draw_state
  when RPG::System
   draw_system
  when RPG::Troop
   draw_troop
  when RPG::Weapon
   draw_weapon
  end
 end
 def draw_item_base
  draw_item_name(@data, 4, WLH)
  self.contents.draw_text(4, WLH*2, 292, WLH, @data.description)
 end
 def draw_usable_item
  scope = %W(None One\sEnemy All\sEnemies One\sEnemy*2 Random\sEnemy
  2\sRandom\sEnemies 3\sRandom\sEnemies One\sAlly All\sAllies Dead\sAlly
  All\sDead\sAllies User)[@data.scope]
  occasion = @data.occasion == 0 ? 'Always' : @data.occasion == 1 ?
   'Battle Only' : @data.occasion == 2 ? 'Menu Only' : 'No Use'
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Scope: ' + scope)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Use: ' + occasion)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'Speed: ' + @data.speed.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'Animation: ' + @data.animation_id.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'Common Event: ' + @data.common_event_id.to_s)
 end
 def draw_actor
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Class: ' + @data.class_id.to_s)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Level: ' + @data.initial_level.to_s)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'EXP Base: ' + @data.exp_basis.to_s)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'EXP Inflate: ' + @data.exp_inflation.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'Sprite: ' + @data.character_name)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'Sprite ID: ' + @data.character_index.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'Face: ' + @data.face_name)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'Face ID: ' + @data.face_index.to_s)
  equipment = [@data.weapon_id,@data.armor1_id,@data.armor2_id,@data.armor3_id,
   @data.armor4_id].join(',')
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Equipment: ' + equipment)
  self.contents.draw_text(4, WLH*11, 292, WLH, '2 Hands: ' + @data.two_swords_style.to_s)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'Fixed: ' + @data.fix_equipment.to_s)
  self.contents.draw_text(4, WLH*13, 292, WLH, 'CPU: ' + @data.auto_battle.to_s)
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Guard+: ' + @data.super_guard.to_s)
  self.contents.draw_text(4, WLH*15, 292, WLH, 'Healer: ' + @data.pharmacology.to_s)
  self.contents.draw_text(4, WLH*16, 292, WLH, 'Crit Bonus: ' + @data.critical_bonus.to_s)
 end
 def draw_animation
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'File 1: ' + @data.animation1_name)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Hue 1: ' + @data.animation1_hue.to_s)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'File 2: ' + @data.animation2_name)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'Hue 2: ' + @data.animation2_hue.to_s)
  pos = @data.position == 0 ? 'Head' : @data.position == 1 ? 'Center' :
   @data.position == 2 ? 'Feet' : 'Screen'
  self.contents.draw_text(4, WLH*6, 292, WLH, 'Position: ' + pos)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'Frames: ' + @data.frame_max.to_s)
 end
 def draw_area
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Map: ' + @data.map_id.to_s)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Area:')
  self.contents.draw_text(32, WLH*4, 264, WLH, 'X: ' + @data.rect.x.to_s)
  self.contents.draw_text(32, WLH*5, 264, WLH, 'Y: ' + @data.rect.y.to_s)
  self.contents.draw_text(32, WLH*6, 264, WLH, 'W: ' + @data.rect.width.to_s)
  self.contents.draw_text(32, WLH*7, 264, WLH, 'H: ' + @data.rect.height.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'Encounters: ' + @data.encounter_list.join(','))
 end
 def draw_armor
  draw_item_base
  kind = @data.kind == 0 ? 'Shield' : @data.kind == 1 ? 'Helmet' :
   @data.kind == 2 ? 'Body Armor' : 'Accessory'
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Kind: ' + kind)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Price: ' + @data.price.to_s)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'EVA: ' + @data.eva.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'ATK: ' + @data.atk.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'DEF: ' + @data.def.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'SPI: ' + @data.spi.to_s)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'AGI: ' + @data.agi.to_s)
  self.contents.draw_text(4, WLH*10, 292, WLH, 'No Crit: ' + @data.prevent_critical.to_s)
  self.contents.draw_text(4, WLH*11, 292, WLH, '1/2 MP: ' + @data.half_mp_cost.to_s)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'EXP*2: ' + @data.double_exp_gain.to_s)
  self.contents.draw_text(4, WLH*13, 292, WLH, 'Healing: ' + @data.auto_hp_recover.to_s)
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Elements: ' + @data.element_set.join(','))
  self.contents.draw_text(4, WLH*15, 292, WLH, 'States: ' + @data.state_set.join(','))
 end
 def draw_class
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  pos = @data.position == 0 ? 'Front' : @data.position == 1 ? 'Middle' : 'Back'
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Row: ' + pos)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Custom Skill: ' + @data.skill_name_valid.to_s)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Skill Name: ' + @data.skill_name)
 end
 def draw_common_event
  trigger = %w(Call Autorun Parallel)[@data.trigger]
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Trigger: ' + trigger)
  if @data.trigger > 0
   self.contents.draw_text(4, WLH*3, 292, WLH, 'Switch: ' + @data.switch_id.to_s)
  end
 end
 def draw_enemy
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Sprite: ' + @data.battler_name)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Sprite Hue: ' + @data.battler_hue.to_s)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'HP/MP: ' + @data.maxhp.to_s + '/' + @data.maxmp.to_s)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'ATK: ' + @data.atk.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'DEF: ' + @data.def.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'SPI: ' + @data.spi.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'AGI: ' + @data.agi.to_s)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'EVA: ' + @data.eva.to_s)
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Hit %: ' + @data.hit.to_s)
  self.contents.draw_text(4, WLH*11, 292, WLH, 'EXP: ' + @data.exp.to_s)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'Gold: ' + @data.gold.to_s)
  type = %w(None Item Weapon Armor)[@data.drop_item1.kind]
  if @data.drop_item1.kind > 0
   drop1 = type+' '+@data.drop_item1.item_id.to_s+' 1/'+@data.drop_item1.denominator.to_s
  else
   drop1 = type
  end
  type = %w(None Item Weapon Armor)[@data.drop_item2.kind]
  if @data.drop_item1.kind > 0
   drop2 = type+' '+@data.drop_item2.item_id.to_s+' 1/'+@data.drop_item2.denominator.to_s
  else
   drop2 = type
  end
  self.contents.draw_text(4, WLH*13, 292, WLH, 'Drop 1: ' + drop1)
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Drop 2: ' + drop2)
  self.contents.draw_text(4, WLH*15, 292, WLH, 'Air: ' + @data.levitate.to_s)
  self.contents.draw_text(4, WLH*16, 292, WLH, 'Critical: ' + @data.has_critical.to_s)
 end
 def draw_item
  draw_item_base
  draw_usable_item
  self.contents.draw_text(4, WLH*8,292, WLH, 'Price: ' + @data.price.to_s)
  self.contents.draw_text(4, WLH*9,292, WLH, 'Consumable: ' + @data.consumable.to_s)
  self.contents.draw_text(4, WLH*10,292, WLH, 'HP: ' + @data.hp_recovery_rate.to_s +
   '% + ' + @data.hp_recovery.to_s)
  self.contents.draw_text(4, WLH*11,292, WLH, 'MP: ' + @data.mp_recovery_rate.to_s +
   '% + ' + @data.mp_recovery.to_s)
  type = %w(None HP MP ATK DEF SPI AGI)
  string = type[@data.parameter_type]
  string += ' +' + @data.parameter_points.to_s if @data.parameter_type > 0
  self.contents.draw_text(4, WLH*12,292, WLH, 'Stat: ' + string)
  self.contents.draw_text(4, WLH*13, 292, WLH, 'Damage: ' + @data.base_damage.to_s +
  ' ± ' + @data.variance.to_s + '%')
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Elements: ' + @data.element_set.join(','))
  self.contents.draw_text(4, WLH*15, 292, WLH, '+States: ' + @data.plus_state_set.join(','))
  self.contents.draw_text(4, WLH*16, 292, WLH, '-States: ' + @data.minus_state_set.join(','))
 end
 def draw_mapinfo
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
 end
 def draw_map
  self.contents.draw_text(4, WLH, 292, WLH, 'Width: ' + @data.width.to_s)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Height: ' + @data.height.to_s)
  scroll_type = @data.scroll_type == 0 ? 'None' : @data.scroll_type == 1 ?
   'Vertical' : @data.scroll_type == 2 ? 'Horizontal' : 'Both'
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Scroll: ' + scroll_type)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Auto BGM: ' + @data.autoplay_bgm.to_s)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'BGM: ' + @data.bgm.name)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'Auto BGS: ' + @data.autoplay_bgs.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'BGS: ' + @data.bgs.name)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'Dash: ' + (!@data.disable_dashing).to_s)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'Encounter Rate: ' + @data.encounter_step.to_s)
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Encounters: ' + @data.encounter_list.join(','))
  self.contents.draw_text(4, WLH*11, 292, WLH, 'Parallax: ' + @data.parallax_name)
  self.contents.draw_text(32, WLH*12, 264, WLH, 'Loop X: ' + @data.parallax_loop_x.to_s)
  self.contents.draw_text(32, WLH*13, 264, WLH, 'Loop Y: ' + @data.parallax_loop_y.to_s)
  self.contents.draw_text(32, WLH*14, 264, WLH, 'Scroll X: ' + @data.parallax_sx.to_s)
  self.contents.draw_text(32, WLH*15, 264, WLH, 'Scroll Y: ' + @data.parallax_sy.to_s)
 end
 def draw_skill
  draw_item_base
  draw_usable_item
  self.contents.draw_text(4, WLH*8,292, WLH, 'MP: ' + @data.mp_cost.to_s)
  self.contents.draw_text(4, WLH*9,292, WLH, 'Hit %: ' + @data.hit.to_s)
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Message:')
  self.contents.draw_text(8, WLH*11, 284, WLH, @data.message1)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'Damage: ' + @data.base_damage.to_s +
  ' ± ' + @data.variance.to_s + '%')
  self.contents.draw_text(4, WLH*13, 292, WLH, 'Factors: ' + [@data.atk_f, @data.spi_f].join(','))
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Elements: ' + @data.element_set.join(','))
  self.contents.draw_text(4, WLH*15, 292, WLH, '+States: ' + @data.plus_state_set.join(','))
  self.contents.draw_text(4, WLH*16, 292, WLH, '-States: ' + @data.minus_state_set.join(','))
 end
 def draw_state
  draw_item_name(@data, 4, WLH)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Priority: ' + @data.priority.to_s)
  restriction = %W(None No\sMagic Attack\sEnemies Attack\sParty No\sAction
  No\sAction/Evade)[@data.restriction]
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Restriction: ' + restriction)
  rates = [@data.atk_rate, @data.def_rate, @data.spi_rate, @data.agi_rate].join(',')
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Stat Rates: ' + rates)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'No Block: ' + @data.nonresistance.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'Reversal: ' + @data.offset_by_opposite.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'Poison: ' + @data.slip_damage.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'Blind: ' + @data.reduce_hit_ratio.to_s)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'Battle Only: ' + @data.battle_only.to_s)
  release = ''
  if @data.hold_turn > 0
   release += @data.hold_turn.to_s + ' turns: ' + @data.auto_release_prob.to_s + '% '
  end
  if @data.release_by_damage
   release += 'Damage'
  end
  if release.empty?
   release = 'No cure'
  end
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Release: ' + release)
  elements = @data.element_set.join(',')
  states = @data.state_set.join(',')
  self.contents.draw_text(4, WLH*11, 292, WLH, 'Anti-Ele: ' + elements)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'Cure: ' + states)
  self.contents.draw_text(4, WLH*13, 292, WLH, @data.message1)
  self.contents.draw_text(4, WLH*14, 292, WLH, @data.message2)
  self.contents.draw_text(4, WLH*15, 292, WLH, @data.message3)
  self.contents.draw_text(4, WLH*16, 292, WLH, @data.message4)
 end
 def draw_system
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.game_title)
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Version: ' + @data.version_id.to_s)
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Starting Pos:')
  self.contents.draw_text(32, WLH*4, 264, WLH, 'Map Id: ' + @data.start_map_id.to_s)
  self.contents.draw_text(32, WLH*5, 264, WLH, 'X: ' + @data.start_x.to_s)
  self.contents.draw_text(32, WLH*6, 264, WLH, 'Y: ' + @data.start_y.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'Party: ' + @data.party_members.join(','))
  self.contents.draw_text(4, WLH*8, 292, WLH, 'Title: ' + @data.title_bgm.name)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'Battle: ' + @data.battle_bgm.name)
  self.contents.draw_text(4, WLH*10, 292, WLH, 'Victory: ' + @data.battle_end_me.name)
  self.contents.draw_text(4, WLH*11, 292, WLH, 'Game Over: ' + @data.gameover_me.name)
 end
 def draw_troop
  self.contents.draw_text(4, WLH, 292, WLH, 'Name: ' + @data.name)
  enemies = @data.members.collect{|i| i.enemy_id}
  self.contents.draw_text(4, WLH*2, 292, WLH, 'Enemies: ' + enemies.join(','))
 end
 def draw_weapon
  draw_item_base
  self.contents.draw_text(4, WLH*3, 292, WLH, 'Animation: ' + @data.animation_id.to_s)
  self.contents.draw_text(4, WLH*4, 292, WLH, 'Price: ' + @data.price.to_s)
  self.contents.draw_text(4, WLH*5, 292, WLH, 'Hit %: ' + @data.hit.to_s)
  self.contents.draw_text(4, WLH*6, 292, WLH, 'ATK: ' + @data.atk.to_s)
  self.contents.draw_text(4, WLH*7, 292, WLH, 'DEF: ' + @data.def.to_s)
  self.contents.draw_text(4, WLH*8, 292, WLH, 'SPI: ' + @data.spi.to_s)
  self.contents.draw_text(4, WLH*9, 292, WLH, 'AGI: ' + @data.agi.to_s)
  self.contents.draw_text(4, WLH*10, 292, WLH, '2 Hands: ' + @data.two_handed.to_s)
  self.contents.draw_text(4, WLH*11, 292, WLH, 'First: ' + @data.fast_attack.to_s)
  self.contents.draw_text(4, WLH*12, 292, WLH, 'Attack*2: ' + @data.dual_attack.to_s)
  self.contents.draw_text(4, WLH*13, 292, WLH, 'Crit Bonus: ' + @data.critical_bonus.to_s)
  self.contents.draw_text(4, WLH*14, 292, WLH, 'Elements: ' + @data.element_set.join(','))
  self.contents.draw_text(4, WLH*15, 292, WLH, 'States: ' + @data.state_set.join(','))
 end
end Â
class Scene_PatchMaker < Scene_Base
 def start
  super
  create_menu_background
  @PATCH = [Zlib::Deflate.deflate('')]
  @select_window = Window_DataSelect.new
  @file_window = Window_FileList.new
  @info_window = Window_DataInfo.new
  @mode_window = Window_CurrentMode.new
  @mode_window.visible = false
 end
 def update
  super
  update_windows
  if @select_window.active
   update_data_select
  elsif @file_window.active
   update_file_list
  end
 end
 def terminate
  super
  @select_window.dispose
  @file_window.dispose
  @info_window.dispose
  @mode_window.dispose
 end
 def update_windows
  @select_window.update
  @file_window.update
  @info_window.update
  @mode_window.update
  @info_window.visible = @select_window.selection == '$data_system' || (
   @file_window.active && @file_window.mode != 0)
  @mode_window.set(@select_window.selection)
 end
 def update_data_select
  @info_window.set_data($data_system, @PATCH.include?($data_system))
  if Input.trigger?(Input::C)
   Sound.play_decision
   if @select_window.selection == 'Script'
    @file_window.mode = 0
    @file_window.data = Dir['*.rb']
    @file_window.index = 0
    @file_window.visible = true
    @file_window.active = true
    @select_window.active = false
    @select_window.visible = false
    @mode_window.visible = true
   elsif @select_window.selection == 'Graphics'
    @file_window.mode = 2
    data = Dir['Graphics/**/*.{png,jpg}'].collect{|i| i[9...(i.length-4)]}
    @file_window.data = data
    @file_window.index = 0
    @file_window.visible = true
    @file_window.active = true
    @select_window.active = false
    @select_window.visible = false
    @mode_window.visible = true
   elsif @select_window.selection == '>FINISH'
    make_patch
    $scene = Scene_Map.new
   elsif @select_window.selection == '$data_system'
    if @PATCH.include?($data_system)
     @PATCH.delete($data_system)
    else
     @PATCH << $data_system
    end
   else
    @file_window.mode = 1
    @file_window.data = eval(@select_window.selection)
    @file_window.index = 0
    @file_window.visible = true
    @file_window.active = true
    @select_window.active = false
    @select_window.visible = false
    @mode_window.visible = true
   end
  elsif Input.trigger?(Input::B)
   Sound.play_cancel
   $scene = Scene_Map.new
  end
 end
 def update_file_list
  if @file_window.mode == 2
   if @file_window.data
    bitmap = Cache.load_bitmap('Graphics/' + @file_window.data.split('/')[0] + '/',
    @file_window.data.split('/')[1])
   else
    bitmap = Cache.load_bitmap('', '')
   end
   array = [bitmap, @file_window.data]
   @info_window.set_data(@file_window.data, @PATCH.include?(array))
  else
   @info_window.set_data(@file_window.data, @PATCH.include?(@file_window.data))
  end
  if Input.trigger?(Input::C)
   Sound.play_decision
   if @file_window.mode == 0
    set_script
    @file_window.visible = false
    @file_window.active = false
    @select_window.active = true
    @select_window.visible = true
    @mode_window.visible = false
   elsif @file_window.mode == 1
    return if @file_window.data.nil?
    if @PATCH.include?(@file_window.data)
     @PATCH.delete(@file_window.data)
    else
     @PATCH << @file_window.data
    end
   else
    return if @file_window.data.nil?
    bitmap = Cache.load_bitmap('Graphics/' + @file_window.data.split('/')[0] + '/',
    @file_window.data.split('/')[1])
    array = [bitmap, @file_window.data]
    if @PATCH.include?(array)
     @PATCH.delete(array)
    else
     @PATCH << array
    end
   end
  elsif Input.trigger?(Input::B)
   Sound.play_cancel
   @file_window.visible = false
   @file_window.active = false
   @select_window.active = true
   @select_window.visible = true
   @mode_window.visible = false
  end
 end
 def set_script
  @script_name = @file_window.data
  lines = []
  if @file_window.data
   lines = File.readlines(@file_window.data)
  end
  @PATCH[0] = Zlib::Deflate.deflate(lines.join)
 end
 def make_patch
  name = 'MyPatch'
  if @script_name
   name = File.basename(@script_name, '.rb')
  end
  name += Patcher::EXT
  mtime = Time.now().to_i
  salt = Patcher::SALT[mtime % 54] + Patcher::SALT[(mtime % 54) ^ 53]
  key = Patcher::KEY.crypt(salt)
  gz = Zlib::GzipWriter.open(name)
  gz.comment = key[2..-1]
  gz.mtime = mtime
  gz.orig_name = 'patch_data'
  @PATCH.each {|data| Marshal.dump(data, gz)}
  gz.close
 end
end
Code:
# Include this in your Main script. It will start the patching sequence.
Patcher.start_patcher
Instructions
Setting Up:
1) Change the KEY in the Patcher module. This is the password that lets only authorized patches work.
2) Change the DIR in the Patcher module if you want to use a different folder to get patches from.
3) Change the EXT in the Patcher module to have a different extension for patch files.
4) By rearranging SALT, even more security can be added!
Making a Patch:
1) Add scripts you want into a text file and give the file the extension ".rb". Save this file in your game's main directory. (OPTIONAL)
2) Call Script: $scene = Scene_PatchMaker.new
3) Select the script you want to use in the Script menu. (OPTIONAL IF DATA IS INCLUDED)
4) Select the data you want to include in your patch. Data is categorized, so it is easy to locate. The true/false in the top right corner indicates if the data will be in the patch file. (OPTIONAL IF SCRIPT IS INCLUDED)
5) Select ">FINISH". This will generate your patch file.
6) Rename your patch. The order in which the Game Patcher will load things is in this order: -, _, 0 to 9, A to Z, a-z. Patches that are loaded last can overwrite previously loaded patches.
7) Enjoy your small patch file.
Notes
Does not patch audio files.
VX->XP Conversion Fund
For those who really want this script in XP, please contribute to the $30 fund.
Funds: $0/30