Skip to content

Instantly share code, notes, and snippets.

@UserUnknownFactor
Last active September 6, 2024 14:45
Show Gist options
  • Save UserUnknownFactor/4e700940079109f2430078534f163504 to your computer and use it in GitHub Desktop.
Save UserUnknownFactor/4e700940079109f2430078534f163504 to your computer and use it in GitHub Desktop.
Unpacker/repacker for RPG Maker XP, VX [Ace] games
require 'zlib'
# Some data structures that are common to both VX and VX Ace.
class Rect
def initialize(x, y, width, height)
@x = x
@y = y
@width = width
@height = height
end
class << self
def _load(s)
end
end
end
class Tone
def initialize(red, green, blue, gray = 0.0)
@red = red
@green = green
@blue = blue
@gray = gray
end
def _dump(d = 0)
[@red].pack('d') + [@green].pack('d') + [@blue].pack('d') + [@gray].pack('d')
end
class << self
def _load(s)
red = s[0,8].unpack('d')[0]
blue = s[8,8].unpack('d')[0]
green = s[16,8].unpack('d')[0]
gray = s[24,8].unpack('d')[0]
Tone.new(red, blue, green, gray)
end
end
end
class Color
def initialize(red, green, blue, alpha = 255.0)
@red = red
@green = green
@blue = blue
@alpha = alpha
end
def _dump(d = 0)
[@red].pack('d') + [@green].pack('d') + [@blue].pack('d') + [@alpha].pack('d')
end
class << self
def _load(s)
red = s[0,8].unpack('d')[0]
blue = s[8,8].unpack('d')[0]
green = s[16,8].unpack('d')[0]
alpha = s[24,8].unpack('d')[0]
Color.new(red, blue, green, alpha)
end
end
end
class Table
def initialize(x, y = nil, z = nil)
@dims = 1 + (y.nil?() ? 0:1) + (z.nil?() ? 0:1)
@xsize = x
@ysize = y.nil?() ? 1:y
@zsize = z.nil?() ? 1:z
@data=Array.new(@xsize*@ysize*@zsize, 0)
end
def [](x, y = 0, z = 0)
@data[x + y*@xsize + z*@xsize*@ysize]
end
def []=(*args)
x = args[0]
y = args.size>2 ? args[1]:0
z = args.size>3 ? args[2]:0
v = args.pop
@data[x + y*@xsize + z*@xsize*@ysize]=v
end
def _dump(d = 0)
s = [@dims].pack('L')
s += [@xsize].pack('L') + [@ysize].pack('L') + [@zsize].pack('L')
s += [@xsize*@ysize*@zsize].pack('L')
for z in 0...@zsize
for y in 0...@ysize
for x in 0...@xsize
s += [@data[x + y*@xsize + z*@xsize*@ysize]].pack('S')[0,2]
end
end
end
s
end
attr_reader(:xsize,:ysize,:zsize,:data)
class << self
def _load(s)
dims = s[0,4].unpack('L')[0]
nx = s[4,4].unpack('L')[0]
ny = s[8,4].unpack('L')[0]
nz = s[12,4].unpack('L')[0]
data = []
for i in 10...(s.size/2)
data.push(s[i*2, 2].unpack('S')[0])
end
t = Table.new(nx, (dims >= 2 ? ny:nil), (dims >= 3 ? nz:nil))
n = 0
for z in 0...nz
for y in 0...ny
for x in 0...nx
t[x, y, z] = data[n]
n += 1
end
end
end
t
end
end
end
# Not actually an RPG Maker class, just for convenience.
class Script
def initialize(index, name, text, scripts_path, script_idx)
@index = index
@name = name
@text = Zlib::Inflate.inflate(text).force_encoding('UTF-8')
script_name = "Script" + script_idx.to_s.rjust(3, "0")
@file = scripts_path.join(script_name).sub_ext(".rb")
end
def to_json(*a)
File.binwrite(@file, @text)
File.binwrite(@file.sub_ext('_tran.rb'), @text)
{
'json_class' => self.class.name,
'filename' => @file,
'name' => dump_string(@name),
}.to_json(*a)
end
def self.data_is_script?(data)
data.instance_of?(Array) and data[0].instance_of?(Array) and data[0].length == 3
end
end
require_relative 'common_db'
# This file contains all the RPG data structures for RPG Maker VX.
module RPG
class Actor
def initialize
@id = 0
@name = ""
@class_id = 1
@initial_level = 1
@exp_basis = 25
@exp_inflation = 35
@character_name = ""
@character_index = 0
@face_name = ""
@face_index = 0
@parameters = Table.new(6, 100)
for i in 1..99
@parameters[0,i] = 400+i*50
@parameters[1,i] = 80+i*10
@parameters[2,i] = 15+i*5/4
@parameters[3,i] = 15+i*5/4
@parameters[4,i] = 20+i*5/2
@parameters[5,i] = 20+i*5/2
end
@weapon_id = 0
@armor1_id = 0
@armor2_id = 0
@armor3_id = 0
@armor4_id = 0
@two_swords_style = false
@fix_equipment = false
@auto_battle = false
@super_guard = false
@pharmacology = false
@critical_bonus = false
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Class
def initialize
@id = 0
@name = ""
@position = 0
@weapon_set = []
@armor_set = []
@element_ranks = Table.new(1)
@state_ranks = Table.new(1)
@learnings = []
@skill_name_valid = false
@skill_name = ""
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Learning
def initialize
@level = 1
@skill_id = 1
end
end
end
class Map
def initialize(width, height)
@width = width
@height = height
@scroll_type = 0
@autoplay_bgm = false
@bgm = RPG::AudioFile.new
@autoplay_bgs = false
@bgs = RPG::AudioFile.new("", 80)
@disable_dashing = false
@encounter_list = []
@encounter_step = 30
@parallax_name = ""
@parallax_loop_x = false
@parallax_loop_y = false
@parallax_sx = 0
@parallax_sy = 0
@parallax_show = false
@data = Table.new(width, height, 3)
@events = {}
end
def to_json(*a)
{
'json_class' => self.class.name,
'events' => dump_array(@events.sort)
}.to_json(*a)
end
end
class MapInfo
def initialize
@name = ""
@parent_id = 0
@order = 0
@expanded = false
@scroll_x = 0
@scroll_y = 0
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Area
def initialize
@id = 0
@name = ""
@map_id = 0
@rect = Rect.new(0,0,0,0)
@encounter_list = []
@order = 0
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Event
def initialize(x, y)
@id = 0
@name = ""
@x = x
@y = y
@pages = [RPG::Event::Page.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Page
def initialize
@condition = RPG::Event::Page::Condition.new
@graphic = RPG::Event::Page::Graphic.new
@move_type = 0
@move_speed = 3
@move_frequency = 3
@move_route = RPG::MoveRoute.new
@walk_anime = true
@step_anime = false
@direction_fix = false
@through = false
@priority_type = 0
@trigger = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@switch1_valid = false
@switch2_valid = false
@variable_valid = false
@self_switch_valid = false
@item_valid = false
@actor_valid = false
@switch1_id = 1
@switch2_id = 1
@variable_id = 1
@variable_value = 0
@self_switch_ch = "A"
@item_id = 1
@actor_id = 1
end
end
class Graphic
def initialize
@tile_id = 0
@character_name = ""
@character_index = 0
@direction = 2
@pattern = 0
end
end
end
end
class EventCommand
def initialize(code = 0, indent = 0, parameters = [])
@code = code
@indent = indent
@parameters = parameters
end
attr_accessor :code
attr_accessor :indent
attr_accessor :parameters
def to_json(*a)
obj = {}
obj['json_class'] = self.class.name
(type, is_text) = get_event_type(@code)
obj['type'] = type
if is_text then
obj['parameters'] = dump_parameters(@parameters)
end
obj.to_json(*a)
end
end
class MoveRoute
def initialize
@repeat = true
@skippable = false
@wait = false
@list = [RPG::MoveCommand.new]
end
end
class MoveCommand
def initialize(code = 0, parameters = [])
@code = code
@parameters = parameters
end
end
class BaseItem
def initialize
@id = 0
@name = ""
@icon_index = 0
@description = ""
@note = ""
end
def base_to_json(clsname)
{
'json_class' => clsname,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note)
}
end
def base_translate(tran, info)
@name = translate_string("name", @name, tran, info)
@description = translate_string("description", @description, tran, info)
@note = translate_string("note", @note, tran, info)
end
def base_update(tran, info)
tran = update_string("name", @name, tran, info)
tran = update_string("description", @description, tran, info)
update_string("note", @note, tran, info)
end
end
class UsableItem < BaseItem
def initialize
super
@scope = 0
@occasion = 0
@speed = 0
@animation_id = 0
@common_event_id = 0
@base_damage = 0
@variance = 20
@atk_f = 0
@spi_f = 0
@physical_attack = false
@damage_to_mp = false
@absorb_damage = false
@ignore_defense = false
@element_set = []
@plus_state_set = []
@minus_state_set = []
end
def for_opponent?
return [1, 2, 3, 4, 5, 6].include?(@scope)
end
def for_friend?
return [7, 8, 9, 10, 11].include?(@scope)
end
def for_dead_friend?
return [9, 10].include?(@scope)
end
def for_user?
return [11].include?(@scope)
end
def for_one?
return [1, 3, 4, 7, 9, 11].include?(@scope)
end
def for_two?
return [5].include?(@scope)
end
def for_three?
return [6].include?(@scope)
end
def for_random?
return [4, 5, 6].include?(@scope)
end
def for_all?
return [2, 8, 10].include?(@scope)
end
def dual?
return [3].include?(@scope)
end
def need_selection?
return [1, 3, 7, 9].include?(@scope)
end
def battle_ok?
return [0, 1].include?(@occasion)
end
def menu_ok?
return [0, 2].include?(@occasion)
end
end
class Skill < UsableItem
def initialize
super
@scope = 1
@mp_cost = 0
@hit = 100
@message1 = ""
@message2 = ""
end
def to_json(*a)
data = base_to_json(self.class.name)
data['message1'] = dump_string(@message1)
data['message2'] = dump_string(@message2)
data.to_json(*a)
end
end
class Item < UsableItem
def initialize
super
@scope = 7
@price = 0
@consumable = true
@hp_recovery_rate = 0
@hp_recovery = 0
@mp_recovery_rate = 0
@mp_recovery = 0
@parameter_type = 0
@parameter_points = 0
end
def to_json(*a)
base_to_json(self.class.name).to_json(*a)
end
end
class Weapon < BaseItem
def initialize
super
@animation_id = 0
@price = 0
@hit = 95
@atk = 0
@def = 0
@spi = 0
@agi = 0
@two_handed = false
@fast_attack = false
@dual_attack = false
@critical_bonus = false
@element_set = []
@state_set = []
end
def to_json(*a)
base_to_json(self.class.name).to_json(*a)
end
end
class Armor < BaseItem
def initialize
super
@kind = 0
@price = 0
@eva = 0
@atk = 0
@def = 0
@spi = 0
@agi = 0
@prevent_critical = false
@half_mp_cost = false
@double_exp_gain = false
@auto_hp_recover = false
@element_set = []
@state_set = []
end
def to_json(*a)
base_to_json(self.class.name).to_json(*a)
end
end
class Enemy
def initialize
@id = 0
@name = ""
@battler_name = ""
@battler_hue = 0
@maxhp = 10
@maxmp = 10
@atk = 10
@def = 10
@spi = 10
@agi = 10
@hit = 95
@eva = 5
@exp = 0
@gold = 0
@drop_item1 = RPG::Enemy::DropItem.new
@drop_item2 = RPG::Enemy::DropItem.new
@levitate = false
@has_critical = false
@element_ranks = Table.new(1)
@state_ranks = Table.new(1)
@actions = [RPG::Enemy::Action.new]
@note = ""
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'note' => dump_string(@note)
}.to_json(*a)
end
class DropItem
def initialize
@kind = 0
@item_id = 1
@weapon_id = 1
@armor_id = 1
@denominator = 1
end
end
class Action
def initialize
@kind = 0
@basic = 0
@skill_id = 1
@condition_type = 0
@condition_param1 = 0
@condition_param2 = 0
@rating = 5
end
def skill?
return @kind == 1
end
end
end
class Troop
def initialize
@id = 0
@name = ""
@members = []
@pages = [RPG::BattleEventPage.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Member
def initialize
@enemy_id = 1
@x = 0
@y = 0
@hidden = false
@immortal = false
end
end
class Page
def initialize
@condition = RPG::Troop::Page::Condition.new
@span = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@turn_ending = false
@turn_valid = false
@enemy_valid = false
@actor_valid = false
@switch_valid = false
@turn_a = 0
@turn_b = 0
@enemy_index = 0
@enemy_hp = 50
@actor_id = 1
@actor_hp = 50
@switch_id = 1
end
end
end
end
class State
def initialize
@id = 0
@name = ""
@icon_index = 0
@restriction = 0
@priority = 5
@atk_rate = 100
@def_rate = 100
@spi_rate = 100
@agi_rate = 100
@nonresistance = false
@offset_by_opposite = false
@slip_damage = false
@reduce_hit_ratio = false
@battle_only = true
@release_by_damage = false
@hold_turn = 0
@auto_release_prob = 0
@message1 = ""
@message2 = ""
@message3 = ""
@message4 = ""
@element_set = []
@state_set = []
@note = ""
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'message1' => dump_string(@message1),
'message2' => dump_string(@message2),
'message3' => dump_string(@message3),
'message4' => dump_string(@message4),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Animation
def initialize
@id = 0
@name = ""
@animation1_name = ""
@animation1_hue = 0
@animation2_name = ""
@animation2_hue = 0
@position = 1
@frame_max = 1
@frames = [RPG::Animation::Frame.new]
@timings = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Frame
def initialize
@cell_max = 0
@cell_data = Table.new(0, 0)
end
end
class Timing
def initialize
@frame = 0
@se = RPG::AudioFile.new("", 80)
@flash_scope = 0
@flash_color = Color.new(255,255,255,255)
@flash_duration = 5
end
end
end
class CommonEvent
def initialize
@id = 0
@name = ""
@trigger = 0
@switch_id = 1
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
end
class System
def initialize
@game_title = ""
@version_id = 0
@party_members = [1]
@elements = [nil, ""]
@switches = [nil, ""]
@variables = [nil, ""]
@passages = Table.new(8192)
@boat = RPG::System::Vehicle.new
@ship = RPG::System::Vehicle.new
@airship = RPG::System::Vehicle.new
@title_bgm = RPG::BGM.new
@battle_bgm = RPG::BGM.new
@battle_end_me = RPG::ME.new
@gameover_me = RPG::ME.new
@sounds = []
20.times { @sounds.push(RPG::AudioFile.new) }
@test_battlers = []
@test_troop_id = 1
@start_map_id = 1
@start_x = 0
@start_y = 0
@terms = RPG::System::Terms.new
@battler_name = ""
@battler_hue = 0
@edit_map_id = 1
end
def to_json(*a)
{
'json_class' => self.class.name,
'game_title' => dump_string(@game_title),
'terms' => @terms,
'elements' => dump_array(@elements),
'switches' => dump_array(@switches),
'variables' => dump_array(@variables)
}.to_json(*a)
end
class Vehicle
def initialize
@character_name = ""
@character_index = 0
@bgm = RPG::AudioFile.new
@start_map_id = 0
@start_x = 0
@start_y = 0
end
end
class Terms
def initialize
@level = ""
@level_a = ""
@hp = ""
@hp_a = ""
@mp = ""
@mp_a = ""
@atk = ""
@def = ""
@spi = ""
@agi = ""
@weapon = ""
@armor1 = ""
@armor2 = ""
@armor3 = ""
@armor4 = ""
@weapon1 = ""
@weapon2 = ""
@attack = ""
@skill = ""
@guard = ""
@item = ""
@equip = ""
@status = ""
@save = ""
@game_end = ""
@fight = ""
@escape = ""
@new_game = ""
@continue = ""
@shutdown = ""
@to_title = ""
@cancel = ""
@gold = ""
end
def to_json(*a)
{
'level' => dump_string(@level),
'level_a' => dump_string(@level_a),
'hp' => dump_string(@hp),
'hp_a' => dump_string(@hp_a),
'mp' => dump_string(@mp),
'mp_a' => dump_string(@mp_a),
'atk' => dump_string(@atk),
'def' => dump_string(@def),
'spi' => dump_string(@spi),
'agi' => dump_string(@agi),
'weapon' => dump_string(@weapon),
'armor1' => dump_string(@armor1),
'armor2' => dump_string(@armor2),
'armor3' => dump_string(@armor3),
'armor4' => dump_string(@armor4),
'weapon1' => dump_string(@weapon1),
'weapon2' => dump_string(@weapon2),
'attack' => dump_string(@attack),
'skill' => dump_string(@skill),
'guard' => dump_string(@guard),
'item' => dump_string(@item),
'equip' => dump_string(@equip),
'status' => dump_string(@status),
'save' => dump_string(@save),
'game_end' => dump_string(@game_end),
'fight' => dump_string(@fight),
'escape' => dump_string(@escape),
'new_game' => dump_string(@new_game),
'continue' => dump_string(@continue),
'shutdown' => dump_string(@shutdown),
'to_title' => dump_string(@to_title),
'cancel' => dump_string(@cancel),
'gold' => dump_string(@gold)
}.to_json(*a)
end
end
class TestBattler
def initialize
@actor_id = 1
@level = 1
@weapon_id = 0
@armor1_id = 0
@armor2_id = 0
@armor3_id = 0
@armor4_id = 0
end
end
end
class AudioFile
def initialize(name = "", volume = 100, pitch = 100)
@name = name
@pitch = pitch
@volume = volume
end
end
class BGM < AudioFile
@@last = BGM.new
def play
if @name.empty?
Audio.bgm_stop
@@last = BGM.new
else
Audio.bgm_play("Audio/BGM/" + @name, @volume, @pitch)
@@last = self
end
end
def self.stop
Audio.bgm_stop
@@last = BGM.new
end
def self.fade(time)
Audio.bgm_fade(time)
@@last = BGM.new
end
def self.last
@@last
end
end
class BGS < AudioFile
@@last = BGS.new
def play
if @name.empty?
Audio.bgs_stop
@@last = BGS.new
else
Audio.bgs_play("Audio/BGS/" + @name, @volume, @pitch)
@@last = self
end
end
def self.stop
Audio.bgs_stop
@@last = BGS.new
end
def self.fade(time)
Audio.bgs_fade(time)
@@last = BGS.new
end
def self.last
@@last
end
end
class ME < AudioFile
def play
if @name.empty?
Audio.me_stop
else
Audio.me_play("Audio/ME/" + @name, @volume, @pitch)
end
end
def self.stop
Audio.me_stop
end
def self.fade(time)
Audio.me_fade(time)
end
end
class SE < AudioFile
def play
unless @name.empty?
Audio.se_play("Audio/SE/" + @name, @volume, @pitch)
end
end
def self.stop
Audio.se_stop
end
end
end
# Table of what type of event command the event codes corresponds to.
EVENT_COMMAND_CODES = {
0 => ["Empty", false],
101 => ["Show Text Attributes", false],
102 => ["Show Choices", true],
103 => ["Input Number", false],
108 => ["Comment", true],
111 => ["Conditional Branch", false],
112 => ["Loop", false],
113 => ["Break Loop", false],
115 => ["Exit Event Processing"],
117 => ["Call Common Event", false],
118 => ["Label", false],
119 => ["Jump to Label", false],
121 => ["Control Switches", false],
122 => ["Control Variables", false],
123 => ["Control Self Switch", false],
124 => ["Control Timer", false],
125 => ["Change Gold", false],
126 => ["Change Items", false],
127 => ["Change Weapons", false],
128 => ["Change Armor", false],
129 => ["Change Party Member", false],
132 => ["Change Battle BGM", false],
133 => ["Change Battle End ME", false],
134 => ["Change Save Access", false],
135 => ["Change Menu Access", false],
136 => ["Change Encounter", false],
201 => ["Transfer Player", false],
202 => ["Set Vehicle Location", false],
203 => ["Set Event Location", false],
204 => ["Scroll Map", false],
205 => ["Set Move Route", false],
206 => ["Get on/off Vehicle", false],
211 => ["Change Transparency", false],
212 => ["Show Animation", false],
213 => ["Shot Balloon Icon", false],
214 => ["Erase Event", false],
221 => ["Fadeout Screen", false],
222 => ["Fadein Screen", false],
223 => ["Tint Screen", false],
224 => ["Flash Screen", false],
225 => ["Shake Screen", false],
230 => ["Wait", false],
231 => ["Show Picture", false],
232 => ["Move Picture", false],
233 => ["Rotate Picture", false],
234 => ["Tint Picture", false],
235 => ["Erase Picture", false],
236 => ["Set Weather Effects", false],
241 => ["Play BGM", false],
242 => ["Fadeout BGM", false],
245 => ["Play BGS", false],
246 => ["Fadeout BGS", false],
249 => ["Play ME", false],
250 => ["Play SE", false],
251 => ["Stop SE", false],
301 => ["Battle Processing", false],
302 => ["Shop Processing", false],
303 => ["Name Input Processing", false],
311 => ["Change HP", false],
312 => ["Change MP", false],
313 => ["Change State", false],
314 => ["Recover All", false],
315 => ["Change EXP", false],
316 => ["Change Level", false],
317 => ["Change Parameters", false],
318 => ["Change Skills", false],
319 => ["Change Equipment", false],
320 => ["Change Actor Name", true],
321 => ["Change Actor Class", false],
322 => ["Change Actor Graphic", false],
323 => ["Change Vehicle Graphic", false],
331 => ["Change Enemy HP", false],
332 => ["Change Enemy MP", false],
333 => ["Change Enemy State", false],
334 => ["Enemy Recover All", false],
335 => ["Enemy Appear", false],
336 => ["Enemy Transform", false],
337 => ["Show Battle Animation", false],
339 => ["Force Action", false],
340 => ["Abort Battle", false],
351 => ["Open Menu Screen", false],
352 => ["Open Save Screen", false],
353 => ["Game Over", false],
354 => ["Return to Title Screen", false],
355 => ["Script", true],
401 => ["Show Text", true],
402 => ["When", false],
403 => ["When Cancel", false],
404 => ["Choices End", false],
408 => ["Comment More", true],
411 => ["Else", false],
412 => ["Branch End", false],
413 => ["Repeat Above", false],
505 => ["Move Command", false],
601 => ["If Win", false],
602 => ["If Escape", false],
603 => ["If Lose", false],
604 => ["Battle Processing End", false],
605 => ["Shop Item", false],
655 => ["Script More", true]
}
# Given an event code, returns the type of the event and whether it can contain
# something translatable.
def get_event_type(code)
type = EVENT_COMMAND_CODES[code]
type.nil? ? [code, false] : type
end
def merge_event_commands(commands)
merged_cmds = []
i = 0
while i < commands.length
cmd = commands[i]
match_code = case cmd.code
when 401 then 401 # Show Text
when 108 then 408 # Comment
when 355 then 655 # Script
else 0
end
if match_code != 0 and commands[i+1].code == match_code
params = cmd.parameters
while commands[i+1].code == match_code
i += 1
params.concat commands[i].parameters
end
cmd = RPG::EventCommand.new(cmd.code, cmd.indent, params)
end
merged_cmds.push cmd
i += 1
end
merged_cmds
end
def split_event_commands(commands)
split_cmds = []
commands.each do |cmd|
match_code = case cmd.code
when 401 then 401
when 108 then 408
when 355 then 655
else 0
end
if match_code != 0 and cmd.parameters.length > 1
code = cmd.code
cmd.parameters.each do |p|
split_cmds.push RPG::EventCommand.new(code, cmd.indent, [p])
code = match_code
end
else
split_cmds.push cmd
end
end
split_cmds
end
require_relative 'common_db'
# This file contains all the RPG data structures for RPG Maker VX Ace.
module RPG
class BaseItem
def initialize
@id = 0
@name = ''
@icon_index = 0
@description = ''
@features = []
@note = ''
end
class Feature
def initialize(code = 0, data_id = 0, value = 0)
@code = code
@data_id = data_id
@value = value
end
end
end
class Actor < BaseItem
def initialize
super
@nickname = ''
@class_id = 1
@initial_level = 1
@max_level = 99
@character_name = ''
@character_index = 0
@face_name = ''
@face_index = 0
@equips = [0,0,0,0,0]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'nickname' => dump_string(@nickname),
'description' => dump_string(@description),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Class < BaseItem
def initialize
super
@exp_params = [30,20,30,30]
@params = Table.new(8,100)
(1..99).each do |i|
@params[0,i] = 400+i*50
@params[1,i] = 80+i*10
(2..5).each {|j| @params[j,i] = 15+i*5/4 }
(6..7).each {|j| @params[j,i] = 30+i*5/2 }
end
@learnings = []
@features.push(RPG::BaseItem::Feature.new(23, 0, 1))
@features.push(RPG::BaseItem::Feature.new(22, 0, 0.95))
@features.push(RPG::BaseItem::Feature.new(22, 1, 0.05))
@features.push(RPG::BaseItem::Feature.new(22, 2, 0.04))
@features.push(RPG::BaseItem::Feature.new(41, 1))
@features.push(RPG::BaseItem::Feature.new(51, 1))
@features.push(RPG::BaseItem::Feature.new(52, 1))
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note),
'learnings' => @learnings
}.to_json(*a)
end
class Learning
def initialize
@level = 1
@skill_id = 1
@note = ''
end
def to_json(*a)
{
'json_class' => self.class.name,
'note' => dump_string(@note)
}.to_json(*a)
end
end
end
class UsableItem < BaseItem
def initialize
super
@scope = 0
@occasion = 0
@speed = 0
@success_rate = 100
@repeats = 1
@tp_gain = 0
@hit_type = 0
@animation_id = 0
@damage = RPG::UsableItem::Damage.new
@effects = []
end
class Damage
def initialize
@type = 0
@element_id = 0
@formula = '0'
@variance = 20
@critical = false
end
end
class Effect
def initialize(code = 0, data_id = 0, value1 = 0, value2 = 0)
@code = code
@data_id = data_id
@value1 = value1
@value2 = value2
end
end
end
class Skill < UsableItem
def initialize
super
@scope = 1
@stype_id = 1
@mp_cost = 0
@tp_cost = 0
@message1 = ''
@message2 = ''
@required_wtype_id1 = 0
@required_wtype_id2 = 0
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'message1' => dump_string(@message1),
'message2' => dump_string(@message2),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Item < UsableItem
def initialize
super
@scope = 7
@itype_id = 1
@price = 0
@consumable = true
end
def key_item?
@itype_id == 2
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class EquipItem < BaseItem
def initialize
super
@price = 0
@etype_id = 0
@params = [0] * 8
end
end
class Weapon < EquipItem
def initialize
super
@wtype_id = 0
@animation_id = 0
@features.push(RPG::BaseItem::Feature.new(31, 1, 0))
@features.push(RPG::BaseItem::Feature.new(22, 0, 0))
end
def performance
params[2] + params[4] + params.inject(0) {|r, v| r += v }
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Armor < EquipItem
def initialize
super
@atype_id = 0
@etype_id = 1
@features.push(RPG::BaseItem::Feature.new(22, 1, 0))
end
def performance
params[3] + params[5] + params.inject(0) {|r, v| r += v }
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Enemy < BaseItem
def initialize
super
@battler_name = ''
@battler_hue = 0
@params = [100,0,10,10,10,10,10,10]
@exp = 0
@gold = 0
@drop_items = Array.new(3) { RPG::Enemy::DropItem.new }
@actions = [RPG::Enemy::Action.new]
@features.push(RPG::BaseItem::Feature.new(22, 0, 0.95))
@features.push(RPG::BaseItem::Feature.new(22, 1, 0.05))
@features.push(RPG::BaseItem::Feature.new(31, 1, 0))
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description),
'note' => dump_string(@note)
}.to_json(*a)
end
class DropItem
def initialize
@kind = 0
@data_id = 1
@denominator = 1
end
end
class Action
def initialize
@skill_id = 1
@condition_type = 0
@condition_param1 = 0
@condition_param2 = 0
@rating = 5
end
end
end
class State < BaseItem
def initialize
super
@restriction = 0
@priority = 50
@remove_at_battle_end = false
@remove_by_restriction = false
@auto_removal_timing = 0
@min_turns = 1
@max_turns = 1
@remove_by_damage = false
@chance_by_damage = 100
@remove_by_walking = false
@steps_to_remove = 100
@message1 = ''
@message2 = ''
@message3 = ''
@message4 = ''
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'message1' => dump_string(@message1),
'message2' => dump_string(@message2),
'message3' => dump_string(@message3),
'message4' => dump_string(@message4),
'note' => dump_string(@note)
}.to_json(*a)
end
end
class Map
def initialize(width, height)
@display_name = ''
@tileset_id = 1
@width = width
@height = height
@scroll_type = 0
@specify_battleback = false
@battleback_floor_name = ''
@battleback_wall_name = ''
@autoplay_bgm = false
@bgm = RPG::BGM.new
@autoplay_bgs = false
@bgs = RPG::BGS.new('', 80)
@disable_dashing = false
@encounter_list = []
@encounter_step = 30
@parallax_name = ''
@parallax_loop_x = false
@parallax_loop_y = false
@parallax_sx = 0
@parallax_sy = 0
@parallax_show = false
@note = ''
@data = Table.new(width, height, 4)
@events = {}
end
def to_json(*a)
{
'json_class' => self.class.name,
'display_name' => dump_string(@display_name),
'note' => dump_string(@note),
'events' => dump_array(@events.sort),
}.to_json(*a)
end
class Encounter
def initialize
@troop_id = 1
@weight = 10
@region_set = []
end
end
end
class MapInfo
def initialize
@name = ''
@parent_id = 0
@order = 0
@expanded = false
@scroll_x = 0
@scroll_y = 0
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Event
def initialize(x, y)
@id = 0
@name = ''
@x = x
@y = y
@pages = [RPG::Event::Page.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Page
def initialize
@condition = RPG::Event::Page::Condition.new
@graphic = RPG::Event::Page::Graphic.new
@move_type = 0
@move_speed = 3
@move_frequency = 3
@move_route = RPG::MoveRoute.new
@walk_anime = true
@step_anime = false
@direction_fix = false
@through = false
@priority_type = 0
@trigger = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@switch1_valid = false
@switch2_valid = false
@variable_valid = false
@self_switch_valid = false
@item_valid = false
@actor_valid = false
@switch1_id = 1
@switch2_id = 1
@variable_id = 1
@variable_value = 0
@self_switch_ch = 'A'
@item_id = 1
@actor_id = 1
end
end
class Condition
def initialize
@switch1_valid = false
@switch2_valid = false
@variable_valid = false
@self_switch_valid = false
@item_valid = false
@actor_valid = false
@switch1_id = 1
@switch2_id = 1
@variable_id = 1
@variable_value = 0
@self_switch_ch = 'A'
@item_id = 1
@actor_id = 1
end
end
class RPG::Event::Page::Graphic
def initialize
@tile_id = 0
@character_name = ''
@character_index = 0
@direction = 2
@pattern = 0
end
end
end
end
class EventCommand
def initialize(code = 0, indent = 0, parameters = [])
@code = code
@indent = indent
@parameters = parameters
end
attr_accessor :code
attr_accessor :indent
attr_accessor :parameters
def to_json(*a)
obj = {}
obj['json_class'] = self.class.name
(type, is_text) = get_event_type(@code, @parameters)
obj['type'] = type
if is_text then
obj['parameters'] = dump_parameters(@parameters)
end
obj.to_json(*a)
end
end
class MoveRoute
def initialize
@repeat = true
@skippable = false
@wait = false
@list = [RPG::MoveCommand.new]
end
end
class MoveCommand
def initialize(code = 0, parameters = [])
@code = code
@parameters = parameters
end
end
class Troop
def initialize
@id = 0
@name = ''
@members = []
@pages = [RPG::Troop::Page.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Member
def initialize
@enemy_id = 1
@x = 0
@y = 0
@hidden = false
end
end
class Page
def initialize
@condition = RPG::Troop::Page::Condition.new
@span = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@turn_ending = false
@turn_valid = false
@enemy_valid = false
@actor_valid = false
@switch_valid = false
@turn_a = 0
@turn_b = 0
@enemy_index = 0
@enemy_hp = 50
@actor_id = 1
@actor_hp = 50
@switch_id = 1
end
end
end
end
class Animation
def initialize
@id = 0
@name = ''
@animation1_name = ''
@animation1_hue = 0
@animation2_name = ''
@animation2_hue = 0
@position = 1
@frame_max = 1
@frames = [RPG::Animation::Frame.new]
@timings = []
end
def to_screen?
@position == 3
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Frame
def initialize
@cell_max = 0
@cell_data = Table.new(0, 0)
end
end
class Timing
def initialize
@frame = 0
@se = RPG::SE.new('', 80)
@flash_scope = 0
@flash_color = Color.new(255,255,255,255)
@flash_duration = 5
end
end
end
class Tileset
def initialize
@id = 0
@mode = 1
@name = ''
@tileset_names = Array.new(9).collect{''}
@flags = Table.new(8192)
@flags[0] = 0x0010
(2048..2815).each {|i| @flags[i] = 0x000F}
(4352..8191).each {|i| @flags[i] = 0x000F}
@note = ''
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class CommonEvent
def initialize
@id = 0
@name = ''
@trigger = 0
@switch_id = 1
@list = [RPG::EventCommand.new]
end
def autorun?
@trigger == 1
end
def parallel?
@trigger == 2
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
end
class System
def initialize
@game_title = ''
@version_id = 0
@japanese = true
@party_members = [1]
@currency_unit = ''
@elements = [nil, '']
@skill_types = [nil, '']
@weapon_types = [nil, '']
@armor_types = [nil, '']
@switches = [nil, '']
@variables = [nil, '']
@boat = RPG::System::Vehicle.new
@ship = RPG::System::Vehicle.new
@airship = RPG::System::Vehicle.new
@title1_name = ''
@title2_name = ''
@opt_draw_title = true
@opt_use_midi = false
@opt_transparent = false
@opt_followers = true
@opt_slip_death = false
@opt_floor_death = false
@opt_display_tp = true
@opt_extra_exp = false
@window_tone = Tone.new(0,0,0)
@title_bgm = RPG::BGM.new
@battle_bgm = RPG::BGM.new
@battle_end_me = RPG::ME.new
@gameover_me = RPG::ME.new
@sounds = Array.new(24) { RPG::SE.new }
@test_battlers = []
@test_troop_id = 1
@start_map_id = 1
@start_x = 0
@start_y = 0
@terms = RPG::System::Terms.new
@battleback1_name = ''
@battleback2_name = ''
@battler_name = ''
@battler_hue = 0
@edit_map_id = 1
end
def to_json(*a)
{
'json_class' => self.class.name,
'game_title' => dump_string(@game_title),
'currency_unit' => dump_string(@currency_unit),
'elements' => dump_array(@elements),
'skill_types' => dump_array(@skill_types),
'weapon_types' => dump_array(@weapon_types),
'armor_types' => dump_array(@armor_types),
'terms' => @terms
}.to_json(*a)
end
class Vehicle
def initialize
@character_name = ''
@character_index = 0
@bgm = RPG::BGM.new
@start_map_id = 0
@start_x = 0
@start_y = 0
end
end
class Terms
def initialize
@basic = Array.new(8) {''}
@params = Array.new(8) {''}
@etypes = Array.new(5) {''}
@commands = Array.new(23) {''}
end
def to_json(*a)
{
'json_class' => self.class.name,
'basic' => dump_array(@basic),
'parameters' => dump_array(@params),
'equipment types' => dump_array(@etypes),
'commands' => dump_array(@commands)
}.to_json(*a)
end
end
class TestBattler
def initialize
@actor_id = 1
@level = 1
@equips = [0,0,0,0,0]
end
end
end
class AudioFile
def initialize(name = '', volume = 100, pitch = 100)
@name = name
@volume = volume
@pitch = pitch
end
end
class BGM < AudioFile
@@last = BGM.new
def play(pos = 0)
if @name.empty?
Audio.bgm_stop
@@last = BGM.new
else
Audio.bgm_play('Audio/BGM/' + @name, @volume, @pitch, pos)
@@last = self.clone
end
end
def replay
play(@pos)
end
def self.stop
Audio.bgm_stop
@@last = BGM.new
end
def self.fade(time)
Audio.bgm_fade(time)
@@last = BGM.new
end
def self.last
@@last.pos = Audio.bgm_pos
@@last
end
end
class BGS < AudioFile
@@last = BGS.new
def play(pos = 0)
if @name.empty?
Audio.bgs_stop
@@last = BGS.new
else
Audio.bgs_play('Audio/BGS/' + @name, @volume, @pitch, pos)
@@last = self.clone
end
end
def replay
play(@pos)
end
def self.stop
Audio.bgs_stop
@@last = BGS.new
end
def self.fade(time)
Audio.bgs_fade(time)
@@last = BGS.new
end
def self.last
@@last.pos = Audio.bgs_pos
@@last
end
end
class ME < AudioFile
def play
if @name.empty?
Audio.me_stop
else
Audio.me_play('Audio/ME/' + @name, @volume, @pitch)
end
end
def self.stop
Audio.me_stop
end
def self.fade(time)
Audio.me_fade(time)
end
end
class SE < AudioFile
def play
unless @name.empty?
Audio.se_play('Audio/SE/' + @name, @volume, @pitch)
end
end
def self.stop
Audio.se_stop
end
end
end
# Table of what type of event command the event codes corresponds to.
EVENT_COMMAND_CODES = {
0 => ["Empty", false],
101 => ["Show Text Attributes", false],
102 => ["Show Choices", true],
103 => ["Input Number", false],
104 => ["Select Key Item", false],
105 => ["Show Scrolling Text Attributes", false],
108 => ["Comment", true],
111 => ["Conditional Branch", false],
112 => ["Loop", false],
113 => ["Break Loop", false],
115 => ["Exit Event Processing", false],
117 => ["Call Common Event", false],
118 => ["Label", false],
119 => ["Jump to Label", false],
121 => ["Control Switches", false],
122 => ["Control Variables", false],
123 => ["Control Self Switch", false],
124 => ["Control Timer", false],
125 => ["Change Gold", false],
126 => ["Change Items", false],
127 => ["Change Weapons", false],
128 => ["Change Armor", false],
129 => ["Change Party Member", false],
132 => ["Change Battle BGM", false],
133 => ["Change Battle End ME", false],
134 => ["Change Save Access", false],
135 => ["Change Menu Access", false],
136 => ["Change Encounter", false],
137 => ["Change Formation Access", false],
138 => ["Change Window Color", false],
201 => ["Transfer Player", false],
202 => ["Set Vehicle Location", false],
203 => ["Set Event Location", false],
204 => ["Scroll Map", false],
205 => ["Set Move Route", false],
206 => ["Get on/off Vehicle", false],
211 => ["Change Transparency", false],
212 => ["Show Animation", false],
213 => ["Shot Balloon Icon", false],
214 => ["Erase Event", false],
216 => ["Change Player Followers", false],
217 => ["Gather Followers", false],
221 => ["Fadeout Screen", false],
222 => ["Fadein Screen", false],
223 => ["Tint Screen", false],
224 => ["Flash Screen", false],
225 => ["Shake Screen", false],
230 => ["Wait", false],
231 => ["Show Picture", false],
232 => ["Move Picture", false],
233 => ["Rotate Picture", false],
234 => ["Tint Picture", false],
235 => ["Erase Picture", false],
236 => ["Set Weather Effects", false],
241 => ["Play BGM", false],
242 => ["Fadeout BGM", false],
243 => ["Save BGM", false],
244 => ["Replay BGM", false],
245 => ["Play BGS", false],
246 => ["Fadeout BGS", false],
249 => ["Play ME", false],
250 => ["Play SE", false],
251 => ["Stop SE", false],
261 => ["Play Movie", false],
281 => ["Change Map Display", false],
282 => ["Change Tileset", false],
283 => ["Change Battle Back", false],
284 => ["Change Parallax Back", false],
285 => ["Get Location Info", false],
301 => ["Battle Processing", false],
302 => ["Shop Processing", false],
303 => ["Name Input Processing", false],
311 => ["Change HP", false],
312 => ["Change MP", false],
313 => ["Change State", false],
314 => ["Recover All", false],
315 => ["Change EXP", false],
316 => ["Change Level", false],
317 => ["Change Parameters", false],
318 => ["Change Skills", false],
319 => ["Change Equipment", false],
320 => ["Change Actor Name", true],
321 => ["Change Actor Class", false],
322 => ["Change Actor Graphic", false],
323 => ["Change Vehicle Graphic", false],
324 => ["Change Actor Nickname", true],
331 => ["Change Enemy HP", false],
332 => ["Change Enemy MP", false],
333 => ["Change Enemy State", false],
334 => ["Enemy Recover All", false],
335 => ["Enemy Appear", false],
336 => ["Enemy Transform", false],
337 => ["Show Battle Animation", false],
339 => ["Force Action", false],
340 => ["Abort Battle", false],
351 => ["Open Menu Screen", false],
352 => ["Open Save Screen", false],
353 => ["Game Over", false],
354 => ["Return to Title Screen", false],
355 => ["Script", true],
401 => ["Show Text", true],
402 => ["When", false],
403 => ["When Cancel", false],
404 => ["Choices End", false],
405 => ["Show Scrolling Text", true],
408 => ["Comment More", true],
411 => ["Else", false],
412 => ["Branch End", false],
413 => ["Repeat Above", false],
601 => ["If Win", false],
602 => ["If Escape", false],
603 => ["If Lose", false],
604 => ["Battle Processing End", false],
605 => ["Shop Item", false],
655 => ["Script More", true]
}
# Given an event code, returns the type of the event and whether it can contain
# something translatable.
def get_event_type(code, params)
type = EVENT_COMMAND_CODES[code]
# Control variables can be assigned scripts:
if code == 122 and params[3] == 4 then
type[1] = true
end
type.nil? ? [code, false] : type
end
def merge_event_commands(commands)
merged_cmds = []
i = 0
while i < commands.length
cmd = commands[i]
match_code = case cmd.code
when 401 then 401 # Show Text
when 108 then 408 # Comment
when 355 then 655 # Script
else 0
end
if match_code != 0 and commands[i+1].code == match_code
params = cmd.parameters
while commands[i+1].code == match_code
i += 1
params.concat commands[i].parameters
end
cmd = RPG::EventCommand.new(cmd.code, cmd.indent, params)
end
merged_cmds.push cmd
i += 1
end
merged_cmds
end
def split_event_commands(commands)
split_cmds = []
commands.each do |cmd|
match_code = case cmd.code
when 401 then 401
when 108 then 408
when 355 then 655
else 0
end
if match_code != 0 and cmd.parameters.length > 1
code = cmd.code
cmd.parameters.each do |p|
split_cmds.push RPG::EventCommand.new(code, cmd.indent, [p])
code = match_code
end
else
split_cmds.push cmd
end
end
split_cmds
end
require_relative 'common_db'
# This file contains all the RPG data structures for RPG Maker XP
module RPG
class Actor
def initialize
@id = 0
@name = ""
@class_id = 1
@initial_level = 1
@final_level = 99
@exp_basis = 30
@exp_inflation = 30
@character_name = ""
@character_hue = 0
@battler_name = ""
@battler_hue = 0
@parameters = Table.new(6,100)
for i in 1..99
@parameters[0,i] = 500+i*50
@parameters[1,i] = 500+i*50
@parameters[2,i] = 50+i*5
@parameters[3,i] = 50+i*5
@parameters[4,i] = 50+i*5
@parameters[5,i] = 50+i*5
end
@weapon_id = 0
@armor1_id = 0
@armor2_id = 0
@armor3_id = 0
@armor4_id = 0
@weapon_fix = false
@armor1_fix = false
@armor2_fix = false
@armor3_fix = false
@armor4_fix = false
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Class
def initialize
@id = 0
@name = ""
@position = 0
@weapon_set = []
@armor_set = []
@element_ranks = Table.new(1)
@state_ranks = Table.new(1)
@learnings = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Learning
def initialize
@level = 1
@skill_id = 1
end
end
end
class Skill
def initialize
@id = 0
@name = ""
@icon_name = ""
@description = ""
@scope = 0
@occasion = 1
@animation1_id = 0
@animation2_id = 0
@menu_se = RPG::AudioFile.new("", 80)
@common_event_id = 0
@sp_cost = 0
@power = 0
@atk_f = 0
@eva_f = 0
@str_f = 0
@dex_f = 0
@agi_f = 0
@int_f = 100
@hit = 100
@pdef_f = 0
@mdef_f = 100
@variance = 15
@element_set = []
@plus_state_set = []
@minus_state_set = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description)
}.to_json(*a)
end
end
class Item
def initialize
@id = 0
@name = ""
@icon_name = ""
@description = ""
@scope = 0
@occasion = 0
@animation1_id = 0
@animation2_id = 0
@menu_se = RPG::AudioFile.new("", 80)
@common_event_id = 0
@price = 0
@consumable = true
@parameter_type = 0
@parameter_points = 0
@recover_hp_rate = 0
@recover_hp = 0
@recover_sp_rate = 0
@recover_sp = 0
@hit = 100
@pdef_f = 0
@mdef_f = 0
@variance = 0
@element_set = []
@plus_state_set = []
@minus_state_set = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description)
}.to_json(*a)
end
end
class Weapon
def initialize
@id = 0
@name = ""
@icon_name = ""
@description = ""
@animation1_id = 0
@animation2_id = 0
@price = 0
@atk = 0
@pdef = 0
@mdef = 0
@str_plus = 0
@dex_plus = 0
@agi_plus = 0
@int_plus = 0
@element_set = []
@plus_state_set = []
@minus_state_set = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description)
}.to_json(*a)
end
end
class Armor
def initialize
@id = 0
@name = ""
@icon_name = ""
@description = ""
@kind = 0
@auto_state_id = 0
@price = 0
@pdef = 0
@mdef = 0
@eva = 0
@str_plus = 0
@dex_plus = 0
@agi_plus = 0
@int_plus = 0
@guard_element_set = []
@guard_state_set = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'description' => dump_string(@description)
}.to_json(*a)
end
end
class Enemy
def initialize
@id = 0
@name = ""
@battler_name = ""
@battler_hue = 0
@maxhp = 500
@maxsp = 500
@str = 50
@dex = 50
@agi = 50
@int = 50
@atk = 100
@pdef = 100
@mdef = 100
@eva = 0
@animation1_id = 0
@animation2_id = 0
@element_ranks = Table.new(1)
@state_ranks = Table.new(1)
@actions = [RPG::Enemy::Action.new]
@exp = 0
@gold = 0
@item_id = 0
@weapon_id = 0
@armor_id = 0
@treasure_prob = 100
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Action
def initialize
@kind = 0
@basic = 0
@skill_id = 1
@condition_turn_a = 0
@condition_turn_b = 1
@condition_hp = 100
@condition_level = 1
@condition_switch_id = 0
@rating = 5
end
end
end
class Troop
def initialize
@id = 0
@name = ""
@members = []
@pages = [RPG::BattleEventPage.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Member
def initialize
@enemy_id = 1
@x = 0
@y = 0
@hidden = false
@immortal = false
end
end
class Page
def initialize
@condition = RPG::Troop::Page::Condition.new
@span = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@turn_valid = false
@enemy_valid = false
@actor_valid = false
@switch_valid = false
@turn_a = 0
@turn_b = 0
@enemy_index = 0
@enemy_hp = 50
@actor_id = 1
@actor_hp = 50
@switch_id = 1
end
end
end
end
class State
def initialize
@id = 0
@name = ""
@animation_id = 0
@restriction = 0
@nonresistance = false
@zero_hp = false
@cant_get_exp = false
@cant_evade = false
@slip_damage = false
@rating = 5
@hit_rate = 100
@maxhp_rate = 100
@maxsp_rate = 100
@str_rate = 100
@dex_rate = 100
@agi_rate = 100
@int_rate = 100
@atk_rate = 100
@pdef_rate = 100
@mdef_rate = 100
@eva = 0
@battle_only = true
@hold_turn = 0
@auto_release_prob = 0
@shock_release_prob = 0
@guard_element_set = []
@plus_state_set = []
@minus_state_set = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Event
def initialize(x, y)
@id = 0
@name = ""
@x = x
@y = y
@pages = [RPG::Event::Page.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'pages' => @pages
}.to_json(*a)
end
class Page
def initialize
@condition = RPG::Event::Page::Condition.new
@graphic = RPG::Event::Page::Graphic.new
@move_type = 0
@move_speed = 3
@move_frequency = 3
@move_route = RPG::MoveRoute.new
@walk_anime = true
@step_anime = false
@direction_fix = false
@through = false
@always_on_top = false
@trigger = 0
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
class Condition
def initialize
@switch1_valid = false
@switch2_valid = false
@variable_valid = false
@self_switch_valid = false
@switch1_id = 1
@switch2_id = 1
@variable_id = 1
@variable_value = 0
@self_switch_ch = "A"
end
end
class Graphic
def initialize
@tile_id = 0
@character_name = ""
@character_hue = 0
@direction = 2
@pattern = 0
@opacity = 255
@blend_type = 0
end
end
end
end
class EventCommand
def initialize(code = 0, indent = 0, parameters = [])
@code = code
@indent = indent
@parameters = parameters
end
attr_accessor :code
attr_accessor :indent
attr_accessor :parameters
def to_json(*a)
obj = {}
obj['json_class'] = self.class.name
(type, is_text) = get_event_type(@code)
obj['type'] = type
if is_text then
obj['parameters'] = dump_parameters(@parameters)
end
obj.to_json(*a)
end
end
class MapInfo
def initialize
@name = ""
@parent_id = 0
@order = 0
@expanded = false
@scroll_x = 0
@scroll_y = 0
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class Map
def initialize(width, height)
@tileset_id = 1
@width = width
@height = height
@autoplay_bgm = false
@bgm = RPG::AudioFile.new
@autoplay_bgs = false
@bgs = RPG::AudioFile.new("", 80)
@encounter_list = []
@encounter_step = 30
@data = Table.new(width, height, 3)
@events = {}
end
def to_json(*a)
{
'json_class' => self.class.name,
'events' => dump_array(@events.sort)
}.to_json(*a)
end
end
class MoveRoute
def initialize
@repeat = true
@skippable = false
@list = [RPG::MoveCommand.new]
end
end
class MoveCommand
def initialize(code = 0, parameters = [])
@code = code
@parameters = parameters
end
end
class Animation
def initialize
@id = 0
@name = ""
@animation_name = ""
@animation_hue = 0
@position = 1
@frame_max = 1
@frames = [RPG::Animation::Frame.new]
@timings = []
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
class Frame
def initialize
@cell_max = 0
@cell_data = Table.new(0, 0)
end
end
class Timing
def initialize
@frame = 0
@se = RPG::AudioFile.new("", 80)
@flash_scope = 0
@flash_color = Color.new(255,255,255,255)
@flash_duration = 5
@condition = 0
end
end
end
class Tileset
def initialize
@id = 0
@name = ""
@tileset_name = ""
@autotile_names = [""]*7
@panorama_name = ""
@panorama_hue = 0
@fog_name = ""
@fog_hue = 0
@fog_opacity = 64
@fog_blend_type = 0
@fog_zoom = 200
@fog_sx = 0
@fog_sy = 0
@battleback_name = ""
@passages = Table.new(384)
@priorities = Table.new(384)
@priorities[0] = 5
@terrain_tags = Table.new(384)
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name)
}.to_json(*a)
end
end
class CommonEvent
def initialize
@id = 0
@name = ""
@trigger = 0
@switch_id = 1
@list = [RPG::EventCommand.new]
end
def to_json(*a)
{
'json_class' => self.class.name,
'name' => dump_string(@name),
'commands' => merge_event_commands(@list)
}.to_json(*a)
end
end
class System
def initialize
@magic_number = 0
@party_members = [1]
@elements = [nil, ""]
@switches = [nil, ""]
@variables = [nil, ""]
@windowskin_name = ""
@title_name = ""
@gameover_name = ""
@battle_transition = ""
@title_bgm = RPG::AudioFile.new
@battle_bgm = RPG::AudioFile.new
@battle_end_me = RPG::AudioFile.new
@gameover_me = RPG::AudioFile.new
@cursor_se = RPG::AudioFile.new("", 80)
@decision_se = RPG::AudioFile.new("", 80)
@cancel_se = RPG::AudioFile.new("", 80)
@buzzer_se = RPG::AudioFile.new("", 80)
@equip_se = RPG::AudioFile.new("", 80)
@shop_se = RPG::AudioFile.new("", 80)
@save_se = RPG::AudioFile.new("", 80)
@load_se = RPG::AudioFile.new("", 80)
@battle_start_se = RPG::AudioFile.new("", 80)
@escape_se = RPG::AudioFile.new("", 80)
@actor_collapse_se = RPG::AudioFile.new("", 80)
@enemy_collapse_se = RPG::AudioFile.new("", 80)
@words = RPG::System::Words.new
@test_battlers = []
@test_troop_id = 1
@start_map_id = 1
@start_x = 0
@start_y = 0
@battleback_name = ""
@battler_name = ""
@battler_hue = 0
@edit_map_id = 1
end
def to_json(*a)
{
'json_class' => self.class.name,
'elements' => dump_array(@elements),
'switches' => dump_array(@switches),
'variables' => dump_array(@variables),
'words' => @words
}.to_json(*a)
end
class Words
def initialize
@gold = ""
@hp = ""
@sp = ""
@str = ""
@dex = ""
@agi = ""
@int = ""
@atk = ""
@pdef = ""
@mdef = ""
@weapon = ""
@armor1 = ""
@armor2 = ""
@armor3 = ""
@armor4 = ""
@attack = ""
@skill = ""
@guard = ""
@item = ""
@equip = ""
end
def to_json(*a)
{
'gold' => dump_string(@gold),
'hp' => dump_string(@hp),
'sp' => dump_string(@sp),
'str' => dump_string(@str),
'dex' => dump_string(@dex),
'agi' => dump_string(@agi),
'int' => dump_string(@int),
'atk' => dump_string(@atk),
'pdef' => dump_string(@pdef),
'mdef' => dump_string(@mdef),
'weapon' => dump_string(@weapon),
'armor1' => dump_string(@armor1),
'armor2' => dump_string(@armor2),
'armor3' => dump_string(@armor3),
'armor4' => dump_string(@armor4),
'attack' => dump_string(@attack),
'skill' => dump_string(@skill),
'guard' => dump_string(@guard),
'item' => dump_string(@item),
'equip' => dump_string(@equip)
}.to_json(*a)
end
end
class TestBattler
def initialize
@actor_id = 1
@level = 1
@weapon_id = 0
@armor1_id = 0
@armor2_id = 0
@armor3_id = 0
@armor4_id = 0
end
end
end
class AudioFile
def initialize(name = "", volume = 100, pitch = 100)
@name = name
@volume = volume
@pitch = pitch
end
end
end
# Table of what type of event command the event codes corresponds to.
EVENT_COMMAND_CODES = {
0 => ["Empty", false],
101 => ["Show Text", true],
102 => ["Show Choices", true],
103 => ["Input Number", false],
104 => ["Change Text Options", false],
105 => ["Button Input Processing", false],
106 => ["Wait", false],
108 => ["Comment", true],
111 => ["Conditional Branch", false],
112 => ["Loop", false],
113 => ["Break Loop", false],
115 => ["Exit Event Processing"],
116 => ["Erase Event"],
117 => ["Call Common Event", false],
118 => ["Label", false],
119 => ["Jump to Label", false],
121 => ["Control Switches", false],
122 => ["Control Variables", false],
123 => ["Control Self Switch", false],
124 => ["Control Timer", false],
125 => ["Change Gold", false],
126 => ["Change Items", false],
127 => ["Change Weapons", false],
128 => ["Change Armor", false],
129 => ["Change Party Member", false],
131 => ["Change Windowskin", false],
132 => ["Change Battle BGM", false],
133 => ["Change Battle End ME", false],
134 => ["Change Save Access", false],
135 => ["Change Menu Access", false],
136 => ["Change Encounter", false],
201 => ["Transfer Player", false],
202 => ["Set Event Location", false],
203 => ["Scroll Map", false],
204 => ["Change Map Settings", false],
205 => ["Change Fog Color Tone", false],
206 => ["Change Fog Opacity", false],
207 => ["Show Animation", false],
208 => ["Change Transparent Flag", false],
209 => ["Set Move Route", false],
210 => ["Wait for Move's Completion", false],
221 => ["Prepare for Transition", false],
222 => ["Execute Transition", false],
223 => ["Change Screen Color Tone", false],
224 => ["Screen Flash", false],
225 => ["Screen Shake", false],
231 => ["Show Picture", false],
232 => ["Move Picture", false],
233 => ["Rotate Picture", false],
234 => ["Change Picture Color Tone", false],
235 => ["Erase Picture", false],
236 => ["Set Weather Effects", false],
241 => ["Play BGM", false],
242 => ["Fade Out BGM", false],
245 => ["Play BGS", false],
246 => ["Fade Out BGS", false],
247 => ["Memorize BGM/BGS", false],
248 => ["Restore BGM/BGS", false],
249 => ["Play ME", false],
250 => ["Play SE", false],
251 => ["Stop SE", false],
301 => ["Battle Processing", false],
302 => ["Shop Processing", false],
303 => ["Name Input Processing", false],
311 => ["Change HP", false],
312 => ["Change SP", false],
313 => ["Change State", false],
314 => ["Recover All", false],
315 => ["Change EXP", false],
316 => ["Change Level", false],
317 => ["Change Parameters", false],
318 => ["Change Skills", false],
319 => ["Change Equipment", false],
320 => ["Change Actor Name", true],
321 => ["Change Actor Class", false],
322 => ["Change Actor Graphic", false],
331 => ["Change Enemy HP", false],
332 => ["Change Enemy SP", false],
333 => ["Change Enemy State", false],
334 => ["Enemy Recover All", false],
335 => ["Enemy Appearance", false],
336 => ["Enemy Transform", false],
337 => ["Show Battle Animation", false],
338 => ["Deal Damage", false],
339 => ["Force Action", false],
340 => ["Abort Battle", false],
351 => ["Call Menu Screen", false],
352 => ["Call Save Screen", false],
353 => ["Game Over", false],
354 => ["Return to Title Screen", false],
355 => ["Script", true],
401 => ["Show Text More", true],
402 => ["When", false],
403 => ["When Cancel", false],
404 => ["Choices End", false],
408 => ["Comment More", true],
411 => ["Else", false],
412 => ["Branch End", false],
413 => ["Repeat Above", false],
509 => ["Move Command", false],
601 => ["If Win", false],
602 => ["If Escape", false],
603 => ["If Lose", false],
604 => ["Battle Processing End", false],
605 => ["Shop Item", false],
655 => ["Script More", true]
}
# Given an event code, returns the type of the event and whether it can contain
# something translatable.
def get_event_type(code)
type = EVENT_COMMAND_CODES[code]
type.nil? ? [code, false] : type
end
def merge_event_commands(commands)
merged_cmds = []
i = 0
while i < commands.length
cmd = commands[i]
match_code = case cmd.code
when 101 then 401 # Show Text
when 108 then 408 # Comment
when 355 then 655 # Script
else 0
end
if match_code != 0 and commands[i+1].code == match_code
params = cmd.parameters
while commands[i+1].code == match_code
i += 1
params.concat commands[i].parameters
end
cmd = RPG::EventCommand.new(cmd.code, cmd.indent, params)
end
merged_cmds.push cmd
i += 1
end
merged_cmds
end
def split_event_commands(commands)
split_cmds = []
commands.each do |cmd|
match_code = case cmd.code
when 101 then 401
when 108 then 408
when 355 then 655
else 0
end
if match_code != 0 and cmd.parameters.length > 1
code = cmd.code
cmd.parameters.each do |p|
split_cmds.push RPG::EventCommand.new(code, cmd.indent, [p])
code = match_code
end
else
split_cmds.push cmd
end
end
split_cmds
end
#!/usr/bin/env ruby
# coding: utf-8
require 'yaml'
require 'zlib'
require_relative 'rmvxace_db'
if not File.exists?('translation_out')
Dir.mkdir('translation_out')
end
if not File.exists?('translation_out/Data')
Dir.mkdir('translation_out/Data')
end
[
'translation_out/Data/Actors.yml',
'translation_out/Data/Animations.yml',
'translation_out/Data/Armors.yml',
'translation_out/Data/Classes.yml',
'translation_out/Data/CommonEvents.yml',
'translation_out/Data/Enemies.yml',
'translation_out/Data/Items.yml',
*Dir.glob('translation_out/Data/Map[0-9][0-9][0-9].yml'),
'translation_out/Data/MapInfos.yml',
'translation_out/Data/Skills.yml',
'translation_out/Data/States.yml',
'translation_out/Data/System.yml',
'translation_out/Data/Tilesets.yml',
'translation_out/Data/Troops.yml',
'translation_out/Data/Weapons.yml'
].each do |yml|
if not File.exists?(yml); next end
data = ''
data = YAML.load_file(yml)
out_file = 'translation_out/Data/'+File.basename(yml,'.yml')+'.rvdata2'
if not File.exists?(out_file)
puts "Packaging... #{out_file}"
File.open(out_file, 'wb') do |file|
file.write(Marshal.dump(data))
end
end
end
if not File.exists?('Data/Scripts'); exit end
puts "Packaging... translation_out/Data/Scripts.rvdata2"
data_old = Marshal.load(File.open('Data/Scripts.rvdata2', 'rb'))
class Array
def row_index(item, column)
self.each_with_index{|raw, i| return i if raw[column] == item}
return
end
end
Dir.glob('Data/Scripts/*.rb') do |rb|
name = File.basename(rb, '.rb')
File.open(rb, 'rb') do |file|
script = file.read
if script.length < 100; next end
index_ = data_old.row_index(name, 1)
if index_
oldname = data_old[index_][1]
if not Zlib::Inflate.inflate(data_old[index_][2]).eql? script
puts " Replacing... #{name}"
data_old[index_][2] = Zlib::Deflate.deflate(script)
end
end
end
end
File.open('translation_out/Data/Scripts.rvdata2', 'wb') do |file|
file.write(Marshal.dump(data_old))
end
#!/usr/bin/env ruby
# coding: cp932
require 'yaml'
require 'zlib'
require_relative 'rmxp_db'
if not File.exists?('translation_out')
Dir.mkdir('translation_out')
end
if not File.exists?('translation_out/Data')
Dir.mkdir('translation_out/Data')
end
[
'translation_out/Data/Actors.yml',
'translation_out/Data/Animations.yml',
'translation_out/Data/Armors.yml',
'translation_out/Data/Classes.yml',
'translation_out/Data/CommonEvents.yml',
'translation_out/Data/Enemies.yml',
'translation_out/Data/Items.yml',
*Dir.glob('translation_out/Data/Map[0-9][0-9][0-9].yml'),
'translation_out/Data/MapInfos.yml',
'translation_out/Data/Skills.yml',
'translation_out/Data/States.yml',
'translation_out/Data/System.yml',
'translation_out/Data/Troops.yml',
'translation_out/Data/Weapons.yml'
].each do |yml|
if not File.exists?(yml); next end
data = ''
data = YAML.load_file(yml)
out_file = 'translation_out/Data/'+File.basename(yml,'.yml')+'.rxdata'
if not File.exists?(out_file)
puts "Packaging... #{out_file}"
File.open(out_file, 'wb') do |file|
file.write(Marshal.dump(data))
end
end
end
if not File.exists?('Data/Scripts'); exit end
puts "Packaging... translation_out/Data/Scripts.rxdata"
data_old = Marshal.load(File.open('Data/Scripts.rxdata', 'rb'))
class Array
def row_index(item, column)
self.each_with_index{|raw, i| return i if raw[column] == item}
return
end
end
Dir.glob('Data/Scripts/*.rb') do |rb|
name = File.basename(rb, '.rb')
File.open(rb, 'rb') do |file|
script = file.read
if script.length < 100; next end
index_ = data_old.row_index(name, 1)
if index_
oldname = data_old[index_][1]
if not Zlib::Inflate.inflate(data_old[index_][2]).eql? script
puts " Replacing... #{name}"
data_old[index_][2] = Zlib::Deflate.deflate(script)
end
end
end
end
File.open('translation_out/Data/Scripts.rxdata', 'wb') do |file|
file.write(Marshal.dump(data_old))
end
#!/usr/bin/env ruby
# coding: utf-8
require 'zlib'
require 'psych'
require 'yaml'
require_relative 'rmvxace_db'
module PsychIntegerParsingPatch
def parse_int string
Integer(string.gsub(/[,_]+/, ''))
end
end
Psych::ScalarScanner.prepend(PsychIntegerParsingPatch)
def load_rvdata2(file)
Marshal.load(File.open(file, 'rb'))
end
def save_yaml(file, data)
File.open(file, 'w') do |f|
f.write(YAML.dump(data))
end
end
DATA_NAMES = %w{
Actors Animations Armors
Classes CommonEvents Enemies
Items MapInfos Skills
States System Tilesets
Troops Weapons
}
DATA_NAMES.each do |name|
rvdata_filename = 'Data/' + name + '.rvdata2'
yaml_filename = 'Data/' + name + '.yml'
puts "Unpacking... #{name}"
data = load_rvdata2(rvdata_filename)
save_yaml(yaml_filename, data)
end
# Map
Dir.glob('Data/Map[0-9][0-9][0-9].rvdata2').each do |rvdata_filename|
yaml_filename = 'Data/' + File.basename(rvdata_filename, ".*") + '.yml'
puts "Unpacking... #{rvdata_filename}"
data = load_rvdata2(rvdata_filename)
save_yaml(yaml_filename, data)
end
def cleanup_scripts_rb
if File.exists?('Data/Scripts')
Dir.glob('Data/Scripts/*.rb') do |file|
File::delete(file)
end
else
Dir.mkdir('Data/Scripts')
end
end
# Scripts
def unpack_scripts
data = load_rvdata2('Data/Scripts.rvdata2')
indexes = []
data.each do |id, name, script|
if name.empty?
next
end
#puts "Unpacking... Scripts/#{name}"
indexes << id
File.open('Data/Scripts/'+name+'.rb', 'wb') do |f|
#f.write "# -*- id: #{id} -*-\n"
f.write Zlib::Inflate.inflate(script)
#f.write "\n# -*- END_OF_SCRIPT -*-\n\n"
end
end
File.open('Data/Scripts.yml', 'wb') do |file|
file.write(YAML.dump(indexes))
end
end
puts "Unpacking... Scripts"
cleanup_scripts_rb
unpack_scripts
#!/usr/bin/env ruby
# coding: cp932
require 'zlib'
require 'psych'
require 'zaml'
require_relative 'rmxp_db'
module PsychIntegerParsingPatch
def parse_int string
Integer(string.gsub(/[,_]+/, ''))
end
end
Psych::ScalarScanner.prepend(PsychIntegerParsingPatch)
def load_rvdata2(file)
Marshal.load(File.open(file, 'rb'))
end
def save_yaml(file, data)
File.open(file, 'w:cp932') do |f|
f.write(ZAML.dump(data))
end
end
DATA_NAMES = %w{
Actors Animations Armors
Classes CommonEvents Enemies
Items MapInfos Skills
States System
Troops Weapons
}
DATA_NAMES.each do |name|
rvdata_filename = 'Data/' + name + '.rxdata'
yaml_filename = 'Data/' + name + '.yml'
puts "Unpacking... #{name}"
data = load_rvdata2(rvdata_filename)
save_yaml(yaml_filename, data)
end
# Map
Dir.glob('Data/Map[0-9][0-9][0-9].rxdata').each do |rvdata_filename|
yaml_filename = 'Data/' + File.basename(rvdata_filename, ".*") + '.yml'
puts "Unpacking... #{rvdata_filename}"
data = load_rvdata2(rvdata_filename)
save_yaml(yaml_filename, data)
end
def cleanup_scripts_rb
if File.exists?('Data/Scripts')
Dir.glob('Data/Scripts/*.rb') do |file|
File::delete(file)
end
else
Dir.mkdir('Data/Scripts')
end
end
# Scripts
def unpack_scripts
data = load_rvdata2('Data/Scripts.rxdata')
indexes = []
data.each do |id, name, script|
if name.empty?
next
end
#puts "Unpacking... Scripts/#{name}"
indexes << id
File.open('Data/Scripts/'+name+'.rb', 'wb') do |f|
#f.write "# -*- id: #{id} -*-\n"
f.write Zlib::Inflate.inflate(script)
#f.write "\n# -*- END_OF_SCRIPT -*-\n\n"
end
end
File.open('Data/Scripts.yml', 'wb') do |file|
file.write(ZAML.dump(indexes))
end
end
puts "Unpacking... Scripts"
cleanup_scripts_rb
unpack_scripts
#!/bin/env ruby
# encoding: utf-8
#
# ZAML -- A partial replacement for YAML, writen with speed and code clarity
# in mind. ZAML fixes one YAML bug (loading Exceptions) and provides
# a replacement for YAML.dump() unimaginatively called ZAML.dump(),
# which is faster on all known cases and an order of magnitude faster
# with complex structures.
#
# http://github.com/hallettj/zaml
#
# Authors: Markus Roberts, Jesse Hallett, Ian McIntosh, Igal Koshevoy, Simon Chiang
#
require 'yaml'
class ZAML
VERSION = "0.1.3"
#
# Class Methods
#
def self.dump(stuff, where='')
z = new
stuff.to_zaml(z)
where << z.to_s
end
#
# Instance Methods
#
def initialize
@result = []
@indent = nil
@structured_key_prefix = nil
Label.counter_reset
emit('--- ')
end
def nested(tail=' ')
old_indent = @indent
@indent = "#{@indent || "\n"}#{tail}"
yield
@indent = old_indent
end
class Label
#
# YAML only wants objects in the datastream once; if the same object
# occurs more than once, we need to emit a label ("&idxxx") on the
# first occurrence and then emit a back reference (*idxxx") on any
# subsequent occurrence(s).
#
# To accomplish this we keeps a hash (by object id) of the labels of
# the things we serialize as we begin to serialize them. The labels
# initially serialize as an empty string (since most objects are only
# going to be be encountered once), but can be changed to a valid
# (by assigning it a number) the first time it is subsequently used,
# if it ever is. Note that we need to do the label setup BEFORE we
# start to serialize the object so that circular structures (in
# which we will encounter a reference to the object as we serialize
# it can be handled).
#
def self.counter_reset
@@previously_emitted_object = {}
@@next_free_label_number = 0
end
def initialize(obj,indent)
@indent = indent
@this_label_number = nil
@@previously_emitted_object[obj.object_id] = self
end
def to_s
@this_label_number ? ('&id%03d%s' % [@this_label_number, @indent]) : ''
end
def reference
@this_label_number ||= (@@next_free_label_number += 1)
@reference ||= '*id%03d' % @this_label_number
end
def self.for(obj)
@@previously_emitted_object[obj.object_id]
end
end
def new_label_for(obj)
Label.new(obj,(Hash === obj || Array === obj) ? "#{@indent || "\n"} " : ' ')
end
def first_time_only(obj)
if label = Label.for(obj)
emit(label.reference)
else
if @structured_key_prefix and not obj.is_a? String
emit(@structured_key_prefix)
@structured_key_prefix = nil
end
emit(new_label_for(obj))
yield
end
end
def emit(s)
@result << s
@recent_nl = false unless s.kind_of?(Label)
end
def nl(s='')
emit(@indent || "\n") unless @recent_nl
emit(s)
@recent_nl = true
end
def to_s
@result.join
end
def prefix_structured_keys(x)
@structured_key_prefix = x
yield
nl unless @structured_key_prefix
@structured_key_prefix = nil
end
end
################################################################
#
# Behavior for custom classes
#
################################################################
class Object
def to_yaml_properties
instance_variables.sort # Default YAML behavior
end
def zamlized_class_name(root)
"!ruby/#{root.name.downcase}#{self.class == root ? '' : ":#{self.class.name}"}"
end
def to_zaml(z)
z.first_time_only(self) {
z.emit(zamlized_class_name(Object))
z.nested {
instance_variables = to_yaml_properties
if instance_variables.empty?
z.emit(" {}")
else
instance_variables.each { |v|
z.nl
v[1..-1].to_zaml(z) # Remove leading '@'
z.emit(': ')
instance_variable_get(v).to_zaml(z)
}
end
}
}
end
end
################################################################
#
# Behavior for built-in classes
#
################################################################
class NilClass
def to_zaml(z)
z.emit('') # NOTE: blank turns into nil in YAML.load
end
end
class Symbol
def to_zaml(z)
z.emit(self.inspect)
end
end
class TrueClass
def to_zaml(z)
z.emit('true')
end
end
class FalseClass
def to_zaml(z)
z.emit('false')
end
end
class Numeric
def to_zaml(z)
z.emit(self)
end
end
class Regexp
def to_zaml(z)
z.first_time_only(self) { z.emit("#{zamlized_class_name(Regexp)} #{inspect}") }
end
end
class Exception
def to_zaml(z)
z.emit(zamlized_class_name(Exception))
z.nested {
z.nl("message: ")
message.to_zaml(z)
}
end
#
# Monkey patch for buggy Exception restore in YAML
#
# This makes it work for now but is not very future-proof; if things
# change we'll most likely want to remove this. To mitigate the risks
# as much as possible, we test for the bug before appling the patch.
#
if respond_to? :yaml_new and yaml_new(self, :tag, "message" => "blurp").message != "blurp"
def self.yaml_new( klass, tag, val )
o = YAML.object_maker( klass, {} ).exception(val.delete( 'message'))
val.each_pair do |k,v|
o.instance_variable_set("@#{k}", v)
end
o
end
end
end
class String
ZAML_ESCAPES = %w{\x00 \x01 \x02 \x03 \x04 \x05 \x06 \a \x08 \t \n \v \f \r \x0e \x0f \x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \e \x1c \x1d \x1e \x1f }
def escaped_for_zaml
gsub( /\x5C/, "\\\\\\" ). # Demi-kludge for Maglev/rubinius; the regexp should be /\\/ but parsetree chokes on that.
gsub( /"/, "\\\"" )
end
def to_zaml(z)
z.first_time_only(self) {
num = '[-+]?(0x)?\d+\.?\d*'
case
when self == ''
self.force_encoding('cp932')
z.emit('""')
when (
(self =~ /\A(true|false|yes|no|on|null|off|#{num}(:#{num})*|!|=|~)$/i) or
(self =~ /\A\n* /) or
(self =~ /[\s:]/) or
(self =~ /^[>|][-+\d]*\s/i) or
(self[-1..-1] =~ /\s/) or
(self =~ /[,\[\]\{\}\r\t]|:\s|\s#/) or
(self =~ /\A([-:?!#&*'"]|<<|%.+:.)/)
)
z.emit("\"#{escaped_for_zaml.force_encoding('cp932')}\"")
when self =~ /\n/
self.force_encoding('cp932')
if self[-1..-1] == "\n" then z.emit('|+') else z.emit('|-') end
z.nested { split("\n",-1).each { |line| z.nl; z.emit(line.chomp("\n")) } }
z.nl
else
self.force_encoding('cp932')
z.emit(self)
end
}
end
end
class Hash
def to_zaml(z)
z.first_time_only(self) {
z.nested {
if empty?
z.emit('{}')
else
each_pair { |k, v|
z.nl
z.prefix_structured_keys('? ') { k.to_zaml(z) }
z.emit(': ')
v.to_zaml(z)
}
end
}
}
end
end
class Array
def to_zaml(z)
z.first_time_only(self) {
z.nested {
if empty?
z.emit('[]')
else
each { |v| z.nl('- '); v.to_zaml(z) }
end
}
}
end
end
class Time
def to_zaml(z)
# 2008-12-06 10:06:51.373758 -07:00
ms = ("%0.6f" % (usec * 1e-6)).sub(/^\d+\./,'')
offset = "%+0.2i:%0.2i" % [utc_offset / 3600, (utc_offset / 60) % 60]
z.emit(self.strftime("%Y-%m-%d %H:%M:%S.#{ms} #{offset}"))
end
end
class Date
def to_zaml(z)
z.emit(strftime('%Y-%m-%d'))
end
end
class Range
def to_zaml(z)
z.first_time_only(self) {
z.emit(zamlized_class_name(Range))
z.nested {
z.nl
z.emit('begin: ')
z.emit(first)
z.nl
z.emit('end: ')
z.emit(last)
z.nl
z.emit('excl: ')
z.emit(exclude_end?)
}
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment