Rearranged some script files

This commit is contained in:
Maruno17
2020-09-05 22:34:32 +01:00
parent 5d3189174c
commit 5073f86190
188 changed files with 250 additions and 239 deletions

View File

@@ -0,0 +1,657 @@
#===============================================================================
# Checking for files and directories
#===============================================================================
# Works around a problem with FileTest.directory if directory contains accent marks
def safeIsDirectory?(f)
ret = false
Dir.chdir(f) { ret = true } rescue nil
return ret
end
# Works around a problem with FileTest.exist if path contains accent marks
def safeExists?(f)
return FileTest.exist?(f) if f[/\A[\x20-\x7E]*\z/]
ret = false
begin
File.open(f,"rb") { ret = true }
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
ret = false
end
return ret
end
# Similar to "Dir.glob", but designed to work around a problem with accessing
# files if a path contains accent marks.
# "dir" is the directory path, "wildcard" is the filename pattern to match.
def safeGlob(dir,wildcard)
ret = []
afterChdir = false
begin
Dir.chdir(dir) {
afterChdir = true
Dir.glob(wildcard) { |f| ret.push(dir+"/"+f) }
}
rescue Errno::ENOENT
raise if afterChdir
end
if block_given?
ret.each { |f| yield(f) }
end
return (block_given?) ? nil : ret
end
# Finds the real path for an image file. This includes paths in encrypted
# archives. Returns nil if the path can't be found.
def pbResolveBitmap(x)
return nil if !x
noext = x.gsub(/\.(bmp|png|gif|jpg|jpeg)$/,"")
filename = nil
# RTP.eachPathFor(x) { |path|
# filename = pbTryString(path) if !filename
# filename = pbTryString(path+".gif") if !filename
# }
RTP.eachPathFor(noext) { |path|
filename = pbTryString(path+".png") if !filename
filename = pbTryString(path+".gif") if !filename
# filename = pbTryString(path+".jpg") if !filename
# filename = pbTryString(path+".jpeg") if !filename
# filename = pbTryString(path+".bmp") if !filename
}
return filename
end
# Finds the real path for an image file. This includes paths in encrypted
# archives. Returns _x_ if the path can't be found.
def pbBitmapName(x)
ret = pbResolveBitmap(x)
return (ret) ? ret : x
end
def getUnicodeString(addr)
return "" if addr==0
rtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
ret = ""
data = "xx"
index = (addr.is_a?(String)) ? 0 : addr
loop do
if addr.is_a?(String)
data = addr[index,2]
else
rtlMoveMemory_pi.call(data, index, 2)
end
codepoint = data.unpack("v")[0]
break if codepoint==0
index += 2
if codepoint<=0x7F
ret += codepoint.chr
elsif codepoint<=0x7FF
ret += (0xC0|((codepoint>>6)&0x1F)).chr
ret += (0x80|(codepoint &0x3F)).chr
elsif codepoint<=0xFFFF
ret += (0xE0|((codepoint>>12)&0x0F)).chr
ret += (0x80|((codepoint>>6)&0x3F)).chr
ret += (0x80|(codepoint &0x3F)).chr
elsif codepoint<=0x10FFFF
ret += (0xF0|((codepoint>>18)&0x07)).chr
ret += (0x80|((codepoint>>12)&0x3F)).chr
ret += (0x80|((codepoint>>6)&0x3F)).chr
ret += (0x80|(codepoint &0x3F)).chr
end
end
return ret
end
def getUnicodeStringFromAnsi(addr)
return "" if addr==0
rtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
ret = ""
data = "x"
index = (addr.is_a?(String)) ? 0 : addr
loop do
if addr.is_a?(String)
data = addr[index,1]
else
rtlMoveMemory_pi.call(data, index, 1)
end
index += 1
codepoint = data.unpack("C")[0]
break if codepoint==0 || !codepoint
break if codepoint==0
if codepoint<=0x7F
ret += codepoint.chr
else
ret += (0xC0|((codepoint>>6)&0x1F)).chr
ret += (0x80|(codepoint &0x3F)).chr
end
end
return ret
end
def getKnownFolder(guid)
packedGuid = guid.pack("VvvC*")
shGetKnownFolderPath = Win32API.new("shell32.dll","SHGetKnownFolderPath","pllp","i") rescue nil
coTaskMemFree = Win32API.new("ole32.dll","CoTaskMemFree","i","") rescue nil
return "" if !(shGetKnownFolderPath && coTaskMemFree)
path = "\0"*4
ret = shGetKnownFolderPath.call(packedGuid,0,0,path)
path = path.unpack("V")[0]
ret = getUnicodeString(path)
coTaskMemFree.call(path)
return ret
end
module RTP
@rtpPaths = nil
def self.exists?(filename,extensions=[])
return false if !filename || filename==""
eachPathFor(filename) { |path|
return true if safeExists?(path)
for ext in extensions
return true if safeExists?(path+ext)
end
}
return false
end
def self.getImagePath(filename)
return self.getPath(filename,["",".png",".gif"]) # ".jpg",".bmp",".jpeg"
end
def self.getAudioPath(filename)
return self.getPath(filename,["",".mp3",".wav",".wma",".mid",".ogg",".midi"])
end
def self.getPath(filename,extensions=[])
return filename if !filename || filename==""
eachPathFor(filename) { |path|
return path if safeExists?(path)
for ext in extensions
file = path+ext
return file if safeExists?(file)
end
}
return filename
end
# Gets the absolute RGSS paths for the given file name
def self.eachPathFor(filename)
return if !filename
if filename[/^[A-Za-z]\:[\/\\]/] || filename[/^[\/\\]/]
# filename is already absolute
yield filename
else
# relative path
RTP.eachPath { |path|
if path=="./"
yield filename
else
yield path+filename
end
}
end
end
# Gets all RGSS search paths
def self.eachPath
# XXX: Use "." instead of Dir.pwd because of problems retrieving files if
# the current directory contains an accent mark
yield ".".gsub(/[\/\\]/,"/").gsub(/[\/\\]$/,"")+"/"
if !@rtpPaths
tmp = Sprite.new
isRgss2 = tmp.respond_to?("wave_amp")
tmp.dispose
@rtpPaths = []
if isRgss2
rtp = getGameIniValue("Game","RTP")
if rtp!=""
rtp = MiniRegistry.get(MiniRegistry::HKEY_LOCAL_MACHINE,
"SOFTWARE\\Enterbrain\\RGSS2\\RTP",rtp,nil)
if rtp && safeIsDirectory?(rtp)
@rtpPaths.push(rtp.sub(/[\/\\]$/,"")+"/")
end
end
else
%w( RTP1 RTP2 RTP3 ).each { |v|
rtp = getGameIniValue("Game",v)
if rtp!=""
rtp = MiniRegistry.get(MiniRegistry::HKEY_LOCAL_MACHINE,
"SOFTWARE\\Enterbrain\\RGSS\\RTP",rtp,nil)
if rtp && safeIsDirectory?(rtp)
@rtpPaths.push(rtp.sub(/[\/\\]$/,"")+"/")
end
end
}
end
end
@rtpPaths.each { |x| yield x }
end
private
@@folder = nil
def self.getGameIniValue(section,key)
val = "\0"*256
gps = Win32API.new('kernel32', 'GetPrivateProfileString',%w(p p p p l p), 'l')
gps.call(section, key, "", val, 256, ".\\Game.ini")
val.delete!("\0")
return val
end
def self.isDirWritable(dir)
return false if !dir || dir==""
loop do
name = dir.gsub(/[\/\\]$/,"")+"/writetest"
for i in 0...12
name += sprintf("%02X",rand(256))
end
name += ".tmp"
if !safeExists?(name)
retval = false
begin
File.open(name,"wb") { retval = true }
rescue Errno::EINVAL, Errno::EACCES, Errno::ENOENT
ensure
File.delete(name) rescue nil
end
return retval
end
end
end
def self.ensureGameDir(dir)
title = RTP.getGameIniValue("Game","Title")
title = "RGSS Game" if title==""
title = title.gsub(/[^\w ]/,"_")
newdir = dir.gsub(/[\/\\]$/,"")+"/"
# Convert to UTF-8 because of ANSI function
newdir += getUnicodeStringFromAnsi(title)
Dir.mkdir(newdir) rescue nil
ret = safeIsDirectory?(newdir) ? newdir : dir
return ret
end
def self.getSaveFileName(fileName)
return getSaveFolder().gsub(/[\/\\]$/,"")+"/"+fileName
end
def self.getSaveFolder
if !@@folder
# XXX: Use "." instead of Dir.pwd because of problems retrieving files if
# the current directory contains an accent mark
pwd = "."
# Get the known folder path for saved games
savedGames = getKnownFolder([
0x4c5c32ff,0xbb9d,0x43b0,0xb5,0xb4,0x2d,0x72,0xe5,0x4e,0xaa,0xa4])
if savedGames && savedGames!="" && isDirWritable(savedGames)
pwd = ensureGameDir(savedGames)
end
if isDirWritable(pwd)
@@folder = pwd
else
appdata = ENV["LOCALAPPDATA"]
if isDirWritable(appdata)
appdata = ensureGameDir(appdata)
else
appdata = ENV["APPDATA"]
if isDirWritable(appdata)
appdata = ensureGameDir(appdata)
elsif isDirWritable(pwd)
appdata = pwd
else
appdata = "."
end
end
@@folder = appdata
end
end
return @@folder
end
end
module FileTest
Image_ext = ['.bmp', '.png', '.jpg', '.jpeg', '.gif']
Audio_ext = ['.mp3', '.mid', '.midi', '.ogg', '.wav', '.wma']
def self.audio_exist?(filename)
return RTP.exists?(filename,Audio_ext)
end
def self.image_exist?(filename)
return RTP.exists?(filename,Image_ext)
end
end
# Used to determine whether a data file exists (rather than a graphics or
# audio file). Doesn't check RTP, but does check encrypted archives.
def pbRgssExists?(filename)
filename = canonicalize(filename)
if safeExists?("./Game.rgssad") || safeExists?("./Game.rgss2a")
return pbGetFileChar(filename)!=nil
else
return safeExists?(filename)
end
end
# Opens an IO, even if the file is in an encrypted archive.
# Doesn't check RTP for the file.
def pbRgssOpen(file,mode=nil)
#File.open("debug.txt","ab") { |fw| fw.write([file,mode,Time.now.to_f].inspect+"\r\n") }
if !safeExists?("./Game.rgssad") && !safeExists?("./Game.rgss2a")
if block_given?
File.open(file,mode) { |f| yield f }
return nil
else
return File.open(file,mode)
end
end
file = canonicalize(file)
Marshal.neverload = true
begin
str = load_data(file)
ensure
Marshal.neverload = false
end
if block_given?
StringInput.open(str) { |f| yield f }
return nil
else
return StringInput.open(str)
end
end
# Gets at least the first byte of a file. Doesn't check RTP, but does check
# encrypted archives.
def pbGetFileChar(file)
file = canonicalize(file)
if !safeExists?("./Game.rgssad") && !safeExists?("./Game.rgss2a")
return nil if !safeExists?(file)
begin
File.open(file,"rb") { |f| return f.read(1) } # read one byte
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
return nil
end
end
Marshal.neverload = true
str = nil
begin
str = load_data(file)
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, RGSSError
str = nil
ensure
Marshal.neverload = false
end
return str
end
def pbTryString(x)
ret = pbGetFileChar(x)
return (ret!=nil && ret!="") ? x : nil
end
# Gets the contents of a file. Doesn't check RTP, but does check
# encrypted archives.
def pbGetFileString(file)
file = canonicalize(file)
if !(safeExists?("./Game.rgssad") || safeExists?("./Game.rgss2a"))
return nil if !safeExists?(file)
begin
File.open(file,"rb") { |f| return f.read } # read all data
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES
return nil
end
end
Marshal.neverload = true
str = nil
begin
str = load_data(file)
rescue Errno::ENOENT, Errno::EINVAL, Errno::EACCES, RGSSError
str = nil
ensure
Marshal.neverload = false
end
return str
end
#===============================================================================
#
#===============================================================================
module MiniRegistry
HKEY_CLASSES_ROOT = 0x80000000
HKEY_CURRENT_USER = 0x80000001
HKEY_LOCAL_MACHINE = 0x80000002
HKEY_USERS = 0x80000003
FormatMessageA = Win32API.new("kernel32","FormatMessageA","LPLLPLP","L")
RegOpenKeyExA = Win32API.new("advapi32","RegOpenKeyExA","LPLLP","L")
RegCloseKey = Win32API.new("advapi32","RegCloseKey","L","L")
RegQueryValueExA = Win32API.new("advapi32","RegQueryValueExA","LPLPPP","L")
def self.open(hkey,subkey,bit64=false)
key = 0.chr*4
flag = bit64 ? 0x20119 : 0x20019
rg = RegOpenKeyExA.call(hkey, subkey, 0, flag, key)
return nil if rg!=0
key = key.unpack("V")[0]
if block_given?
begin
yield(key)
ensure
check(RegCloseKey.call(key))
end
else
return key
end
end
def self.close(hkey); check(RegCloseKey.call(hkey)) if hkey; end
def self.get(hkey,subkey,name,defaultValue=nil,bit64=false)
self.open(hkey,subkey,bit64) { |key|
return self.read(key,name) rescue defaultValue
}
return defaultValue
end
def self.read(hkey,name)
hkey = 0 if !hkey
type = 0.chr*4
size = 0.chr*4
check(RegQueryValueExA.call(hkey,name,0,type,0,size))
data = " "*size.unpack("V")[0]
check(RegQueryValueExA.call(hkey,name,0,type,data,size))
type = type.unpack("V")[0]
data = data[0,size.unpack("V")[0]]
case type
when 1; return data.chop # REG_SZ
when 2; return data.gsub(/%([^%]+)%/) { ENV[$1] || $& } # REG_EXPAND_SZ
when 3; return data # REG_BINARY
when 4; return data.unpack("V")[0] # REG_DWORD
when 5; return data.unpack("V")[0] # REG_DWORD_BIG_ENDIAN
when 11; qw = data.unpack("VV"); return (data[1]<<32|data[0]) # REG_QWORD
else; raise "Type #{type} not supported."
end
end
private
def self.check(code)
if code!=0
msg = "\0"*1024
len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
raise msg[0, len].tr("\r", '').chomp
end
end
end
class StringInput
include Enumerable
class << self
def new( str )
if block_given?
begin
f = super
yield f
ensure
f.close if f
end
else
super
end
end
alias open new
end
def initialize( str )
@string = str
@pos = 0
@closed = false
@lineno = 0
end
attr_reader :lineno,:string
def inspect
return "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@string[0,30].inspect}>"
end
def close
raise IOError, 'closed stream' if @closed
@pos = nil
@closed = true
end
def closed?; @closed; end
def pos
raise IOError, 'closed stream' if @closed
[@pos, @string.size].min
end
alias tell pos
def rewind; seek(0); end
def pos=(value); seek(value); end
def seek(offset, whence=IO::SEEK_SET)
raise IOError, 'closed stream' if @closed
case whence
when IO::SEEK_SET; @pos = offset
when IO::SEEK_CUR; @pos += offset
when IO::SEEK_END; @pos = @string.size - offset
else
raise ArgumentError, "unknown seek flag: #{whence}"
end
@pos = 0 if @pos < 0
@pos = [@pos, @string.size + 1].min
offset
end
def eof?
raise IOError, 'closed stream' if @closed
@pos > @string.size
end
def each( &block )
raise IOError, 'closed stream' if @closed
begin
@string.each(&block)
ensure
@pos = 0
end
end
def gets
raise IOError, 'closed stream' if @closed
if idx = @string.index(?\n, @pos)
idx += 1 # "\n".size
line = @string[ @pos ... idx ]
@pos = idx
@pos += 1 if @pos == @string.size
else
line = @string[ @pos .. -1 ]
@pos = @string.size + 1
end
@lineno += 1
line
end
def getc
raise IOError, 'closed stream' if @closed
ch = @string[@pos]
@pos += 1
@pos += 1 if @pos == @string.size
ch
end
def read( len = nil )
raise IOError, 'closed stream' if @closed
if !len
return nil if eof?
rest = @string[@pos ... @string.size]
@pos = @string.size + 1
return rest
end
str = @string[@pos, len]
@pos += len
@pos += 1 if @pos == @string.size
str
end
def read_all; read(); end
alias sysread read
end
module ::Marshal
class << self
if !@oldloadAliased
alias oldload load
@oldloadAliased = true
end
@@neverload = false
def neverload
return @@neverload
end
def neverload=(value)
@@neverload = value
end
def load(port,*arg)
if @@neverload
if port.is_a?(IO)
return port.read
end
return port
end
oldpos = port.pos if port.is_a?(IO)
begin
oldload(port,*arg)
rescue
p [$!.class,$!.message,$!.backtrace]
if port.is_a?(IO)
port.pos = oldpos
return port.read
end
return port
end
end
end
end

View File

@@ -0,0 +1,163 @@
module FileInputMixin
def fgetb
x=0
ret=0
each_byte do |i|
ret=i || 0
break
end
return ret
end
def fgetw
x=0
ret=0
each_byte do |i|
break if !i
ret|=(i<<x)
x+=8
break if x==16
end
return ret
end
def fgetdw
x=0
ret=0
each_byte do |i|
break if !i
ret|=(i<<x)
x+=8
break if x==32
end
return ret
end
def fgetsb
ret=fgetb
if (ret&0x80)!=0
return ret-256
else
return ret
end
end
def xfgetb(offset)
self.pos=offset
return fgetb
end
def xfgetw(offset)
self.pos=offset
return fgetw
end
def xfgetdw(offset)
self.pos=offset
return fgetdw
end
def getOffset(index)
self.binmode
self.pos=0
offset=fgetdw>>3
return 0 if index>=offset
self.pos=index*8
return fgetdw
end
def getLength(index)
self.binmode
self.pos=0
offset=fgetdw>>3
return 0 if index>=offset
self.pos=index*8+4
return fgetdw
end
def readName(index)
self.binmode
self.pos=0
offset=fgetdw>>3
return "" if index>=offset
self.pos=index<<3
offset=fgetdw
length=fgetdw
return "" if length==0
self.pos=offset
return read(length)
end
end
module FileOutputMixin
def fputb(b)
b=b&0xFF
write(b.chr)
end
def fputw(w)
2.times do
b=w&0xFF
write(b.chr)
w>>=8
end
end
def fputdw(w)
4.times do
b=w&0xFF
write(b.chr)
w>>=8
end
end
end
class File < IO
=begin
unless defined?(debugopen)
class << self
alias debugopen open
end
end
def open(f,m="r")
debugopen("debug.txt","ab") { |file| file.write([f,m,Time.now.to_f].inspect+"\r\n") }
if block_given?
debugopen(f,m) { |file| yield file }
else
return debugopen(f,m)
end
end
=end
include FileInputMixin
include FileOutputMixin
end
class StringInput
include FileInputMixin
def pos=(value)
seek(value)
end
def each_byte
while !eof?
yield getc
end
end
def binmode
end
end
class StringOutput
include FileOutputMixin
end

View File

@@ -0,0 +1,776 @@
def pbAddScriptTexts(items,script)
script.scan(/(?:_I)\s*\(\s*\"((?:[^\\\"]*\\\"?)*[^\"]*)\"/) { |s|
string=s[0]
string.gsub!(/\\\"/,"\"")
string.gsub!(/\\\\/,"\\")
items.push(string)
}
end
def pbAddRgssScriptTexts(items,script)
script.scan(/(?:_INTL|_ISPRINTF)\s*\(\s*\"((?:[^\\\"]*\\\"?)*[^\"]*)\"/) { |s|
string=s[0]
string.gsub!(/\\r/,"\r")
string.gsub!(/\\n/,"\n")
string.gsub!(/\\1/,"\1")
string.gsub!(/\\\"/,"\"")
string.gsub!(/\\\\/,"\\")
items.push(string)
}
end
def pbSetTextMessages
Graphics.update
begin
t = Time.now.to_i
texts=[]
for script in $RGSS_SCRIPTS
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
scr=Zlib::Inflate.inflate(script[2])
pbAddRgssScriptTexts(texts,scr)
end
# Must add messages because this code is used by both game system and Editor
MessageTypes.addMessagesAsHash(MessageTypes::ScriptTexts,texts)
commonevents=pbLoadRxData("Data/CommonEvents")
items=[]
choices=[]
for event in commonevents.compact
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
begin
neednewline=false
lastitem=""
for j in 0...event.list.size
list = event.list[j]
if neednewline && list.code!=401
if lastitem!=""
lastitem.gsub!(/([^\.\!\?])\s\s+/) { |m| $1+" " }
items.push(lastitem)
lastitem=""
end
neednewline=false
end
if list.code == 101
lastitem+="#{list.parameters[0]}" if !$RPGVX
neednewline=true
elsif list.code == 102
for k in 0...list.parameters[0].length
choices.push(list.parameters[0][k])
end
neednewline=false
elsif list.code == 401
lastitem+=" " if lastitem!=""
lastitem+="#{list.parameters[0]}"
neednewline=true
elsif list.code == 355 || list.code == 655
pbAddScriptTexts(items,list.parameters[0])
elsif list.code == 111 && list.parameters[0]==12
pbAddScriptTexts(items,list.parameters[1])
elsif list.code == 209
route=list.parameters[1]
for k in 0...route.list.size
if route.list[k].code == 45
pbAddScriptTexts(items,route.list[k].parameters[0])
end
end
end
end
if neednewline
if lastitem!=""
items.push(lastitem)
lastitem=""
end
end
end
end
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
items|=[]
choices|=[]
items.concat(choices)
MessageTypes.setMapMessagesAsHash(0,items)
mapinfos = pbLoadRxData("Data/MapInfos")
mapnames=[]
for id in mapinfos.keys
mapnames[id]=mapinfos[id].name
end
MessageTypes.setMessages(MessageTypes::MapNames,mapnames)
for id in mapinfos.keys
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
filename=sprintf("Data/Map%03d.%s",id,$RPGVX ? "rvdata" : "rxdata")
next if !pbRgssExists?(filename)
map = load_data(filename)
items=[]
choices=[]
for event in map.events.values
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
begin
for i in 0...event.pages.size
neednewline=false
lastitem=""
for j in 0...event.pages[i].list.size
list = event.pages[i].list[j]
if neednewline && list.code!=401
if lastitem!=""
lastitem.gsub!(/([^\.\!\?])\s\s+/) { |m| $1+" " }
items.push(lastitem)
lastitem=""
end
neednewline=false
end
if list.code == 101
lastitem+="#{list.parameters[0]}" if !$RPGVX
neednewline=true
elsif list.code == 102
for k in 0...list.parameters[0].length
choices.push(list.parameters[0][k])
end
neednewline=false
elsif list.code == 401
lastitem+=" " if lastitem!=""
lastitem+="#{list.parameters[0]}"
neednewline=true
elsif list.code == 355 || list.code==655
pbAddScriptTexts(items,list.parameters[0])
elsif list.code == 111 && list.parameters[0]==12
pbAddScriptTexts(items,list.parameters[1])
elsif list.code==209
route=list.parameters[1]
for k in 0...route.list.size
if route.list[k].code==45
pbAddScriptTexts(items,route.list[k].parameters[0])
end
end
end
end
if neednewline
if lastitem!=""
items.push(lastitem)
lastitem=""
end
end
end
end
end
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
items|=[]
choices|=[]
items.concat(choices)
MessageTypes.setMapMessagesAsHash(id,items)
if Time.now.to_i - t >= 5
t = Time.now.to_i
Graphics.update
end
end
rescue Hangup
end
Graphics.update
end
def pbEachIntlSection(file)
lineno=1
re=/^\s*\[\s*([^\]]+)\s*\]\s*$/
havesection=false
sectionname=nil
lastsection=[]
file.each_line { |line|
if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
line=line[3,line.length-3]
end
if !line[/^\#/] && !line[/^\s*$/]
if line[re]
if havesection
yield lastsection,sectionname
end
lastsection.clear
sectionname=$~[1]
havesection=true
else
if sectionname==nil
raise _INTL("Expected a section at the beginning of the file (line {1})",lineno)
end
lastsection.push(line.gsub(/\s+$/,""))
end
end
lineno+=1
if lineno%500==0
Graphics.update
end
}
if havesection
yield lastsection,sectionname
end
end
def pbGetText(infile)
begin
file=File.open(infile,"rb")
rescue
raise _INTL("Can't find {1}",infile)
end
intldat=[]
begin
pbEachIntlSection(file) { |section,name|
next if section.length==0
index=name
if !name[/^([Mm][Aa][Pp])?(\d+)$/]
raise _INTL("Invalid section name {1}",name)
end
ismap=$~[1] && $~[1]!=""
id=$~[2].to_i
itemlength=0
if section[0][/^\d+$/]
intlhash=[]
itemlength=3
if ismap
raise _INTL("Section {1} can't be an ordered list (section was recognized as an ordered list because its first line is a number)",name)
end
if section.length%3!=0
raise _INTL("Section {1}'s line count is not divisible by 3 (section was recognized as an ordered list because its first line is a number)",name)
end
else
intlhash=OrderedHash.new
itemlength=2
if section.length%2!=0
raise _INTL("Section {1} has an odd number of entries (section was recognized as a hash because its first line is not a number)",name)
end
end
i=0;loop do break unless i<section.length
if itemlength==3
if !section[i][/^\d+$/]
raise _INTL("Expected a number in section {1}, got {2} instead",name,section[i])
end
key=section[i].to_i
i+=1
else
key=MessageTypes.denormalizeValue(section[i])
end
intlhash[key]=MessageTypes.denormalizeValue(section[i+1])
i+=2
end
if ismap
intldat[0]=[] if !intldat[0]
intldat[0][id]=intlhash
else
intldat[id]=intlhash
end
}
ensure
file.close
end
return intldat
end
def pbCompileText
outfile=File.open("intl.dat","wb")
begin
intldat=pbGetText("intl.txt")
Marshal.dump(intldat,outfile)
rescue
raise
ensure
outfile.close
end
end
class OrderedHash < Hash
def initialize
@keys=[]
super
end
def keys
return @keys.clone
end
def inspect
str="{"
for i in 0...@keys.length
str+=", " if i>0
str+=@keys[i].inspect+"=>"+self[@keys[i]].inspect
end
str+="}"
return str
end
alias :to_s :inspect
def []=(key,value)
oldvalue=self[key]
if !oldvalue && value
@keys.push(key)
elsif !value
@keys|=[]
@keys-=[key]
end
return super(key,value)
end
def self._load(string)
ret=self.new
keysvalues=Marshal.load(string)
keys=keysvalues[0]
values=keysvalues[1]
for i in 0...keys.length
ret[keys[i]]=values[i]
end
return ret
end
def _dump(depth=100)
values=[]
for key in @keys
values.push(self[key])
end
return Marshal.dump([@keys,values])
end
end
class Messages
def initialize(filename=nil,delayLoad=false)
@messages=nil
@filename=filename
if @filename && !delayLoad
loadMessageFile(@filename)
end
end
def delayedLoad
if @filename && !@messages
loadMessageFile(@filename)
@filename=nil
end
end
def self.stringToKey(str)
if str && str[/[\r\n\t\1]|^\s+|\s+$|\s{2,}/]
key=str.clone
key.gsub!(/^\s+/,"")
key.gsub!(/\s+$/,"")
key.gsub!(/\s{2,}/," ")
return key
end
return str
end
def self.normalizeValue(value)
if value[/[\r\n\t\x01]|^[\[\]]/]
ret=value.clone
ret.gsub!(/\r/,"<<r>>")
ret.gsub!(/\n/,"<<n>>")
ret.gsub!(/\t/,"<<t>>")
ret.gsub!(/\[/,"<<[>>")
ret.gsub!(/\]/,"<<]>>")
ret.gsub!(/\x01/,"<<1>>")
return ret
end
return value
end
def self.denormalizeValue(value)
if value[/<<[rnt1\[\]]>>/]
ret=value.clone
ret.gsub!(/<<1>>/,"\1")
ret.gsub!(/<<r>>/,"\r")
ret.gsub!(/<<n>>/,"\n")
ret.gsub!(/<<\[>>/,"[")
ret.gsub!(/<<\]>>/,"]")
ret.gsub!(/<<t>>/,"\t")
return ret
end
return value
end
def self.writeObject(f,msgs,secname,origMessages=nil)
return if !msgs
if msgs.is_a?(Array)
f.write("[#{secname}]\r\n")
for j in 0...msgs.length
next if msgs[j]==nil || msgs[j]==""
value=Messages.normalizeValue(msgs[j])
origValue=""
if origMessages
origValue=Messages.normalizeValue(origMessages.get(secname,j))
else
origValue=Messages.normalizeValue(MessageTypes.get(secname,j))
end
f.write("#{j}\r\n")
f.write(origValue+"\r\n")
f.write(value+"\r\n")
end
elsif msgs.is_a?(OrderedHash)
f.write("[#{secname}]\r\n")
keys=msgs.keys
for key in keys
next if msgs[key]==nil || msgs[key]==""
value=Messages.normalizeValue(msgs[key])
valkey=Messages.normalizeValue(key)
# key is already serialized
f.write(valkey+"\r\n")
f.write(value+"\r\n")
end
end
end
def messages
return @messages || []
end
def extract(outfile)
# return if !@messages
origMessages=Messages.new("Data/messages.dat")
File.open(outfile,"wb") { |f|
f.write(0xef.chr)
f.write(0xbb.chr)
f.write(0xbf.chr)
f.write("# To localize this text for a particular language, please\r\n")
f.write("# translate every second line of this file.\r\n")
if origMessages.messages[0]
for i in 0...origMessages.messages[0].length
msgs=origMessages.messages[0][i]
Messages.writeObject(f,msgs,"Map#{i}",origMessages)
end
end
for i in 1...origMessages.messages.length
msgs=origMessages.messages[i]
Messages.writeObject(f,msgs,i,origMessages)
end
}
end
def setMessages(type,array)
@messages=[] if !@messages
arr=[]
for i in 0...array.length
arr[i]=(array[i]) ? array[i] : ""
end
@messages[type]=arr
end
def addMessages(type,array)
@messages=[] if !@messages
arr=(@messages[type]) ? @messages[type] : []
for i in 0...array.length
arr[i]=(array[i]) ? array[i] : (arr[i]) ? arr[i] : ""
end
@messages[type]=arr
end
def self.createHash(type,array)
arr=OrderedHash.new
for i in 0...array.length
if array[i]
key=Messages.stringToKey(array[i])
arr[key]=array[i]
end
end
return arr
end
def self.addToHash(type,array,hash)
if !hash
hash=OrderedHash.new
end
for i in 0...array.length
if array[i]
key=Messages.stringToKey(array[i])
hash[key]=array[i]
end
end
return hash
end
def setMapMessagesAsHash(type,array)
@messages=[] if !@messages
@messages[0]=[] if !@messages[0]
@messages[0][type]=Messages.createHash(type,array)
end
def addMapMessagesAsHash(type,array)
@messages=[] if !@messages
@messages[0]=[] if !@messages[0]
@messages[0][type]=Messages.addToHash(type,array,@messages[0][type])
end
def setMessagesAsHash(type,array)
@messages=[] if !@messages
@messages[type]=Messages.createHash(type,array)
end
def addMessagesAsHash(type,array)
@messages=[] if !@messages
@messages[type]=Messages.addToHash(type,array,@messages[type])
end
def saveMessages(filename=nil)
filename="Data/messages.dat" if !filename
File.open(filename,"wb") { |f| Marshal.dump(@messages,f) }
end
def loadMessageFile(filename)
begin
pbRgssOpen(filename,"rb") { |f| @messages=Marshal.load(f) }
if !@messages.is_a?(Array)
@messages=nil
raise "Corrupted data"
end
return @messages
rescue
@messages=nil
return nil
end
end
def set(type,id,value)
delayedLoad
return if !@messages
return if !@messages[type]
@messages[type][id]=value
end
def getCount(type)
delayedLoad
return 0 if !@messages
return 0 if !@messages[type]
return @messages[type].length
end
def get(type,id)
delayedLoad
return "" if !@messages
return "" if !@messages[type]
return "" if !@messages[type][id]
return @messages[type][id]
end
def getFromHash(type,key)
delayedLoad
return key if !@messages || !@messages[type] || !key
id=Messages.stringToKey(key)
return key if !@messages[type][id]
return @messages[type][id]
end
def getFromMapHash(type,key)
delayedLoad
return key if !@messages
return key if !@messages[0]
return key if !@messages[0][type] && !@messages[0][0]
id=Messages.stringToKey(key)
if @messages[0][type] && @messages[0][type][id]
return @messages[0][type][id]
elsif @messages[0][0] && @messages[0][0][id]
return @messages[0][0][id]
end
return key
end
end
module MessageTypes
# Value 0 is used for common event and map event text
Species = 1
Kinds = 2
Entries = 3
FormNames = 4
Moves = 5
MoveDescriptions = 6
Items = 7
ItemPlurals = 8
ItemDescriptions = 9
Abilities = 10
AbilityDescs = 11
Types = 12
TrainerTypes = 13
TrainerNames = 14
BeginSpeech = 15
EndSpeechWin = 16
EndSpeechLose = 17
RegionNames = 18
PlaceNames = 19
PlaceDescriptions = 20
MapNames = 21
PhoneMessages = 22
TrainerLoseText = 23
ScriptTexts = 24
@@messages = Messages.new
@@messagesFallback = Messages.new("Data/messages.dat",true)
def self.stringToKey(str)
return Messages.stringToKey(str)
end
def self.normalizeValue(value)
return Messages.normalizeValue(value)
end
def self.denormalizeValue(value)
Messages.denormalizeValue(value)
end
def self.writeObject(f,msgs,secname)
Messages.denormalizeValue(str)
end
def self.extract(outfile)
@@messages.extract(outfile)
end
def self.setMessages(type,array)
@@messages.setMessages(type,array)
end
def self.addMessages(type,array)
@@messages.addMessages(type,array)
end
def self.createHash(type,array)
Messages.createHash(type,array)
end
def self.addMapMessagesAsHash(type,array)
@@messages.addMapMessagesAsHash(type,array)
end
def self.setMapMessagesAsHash(type,array)
@@messages.setMapMessagesAsHash(type,array)
end
def self.addMessagesAsHash(type,array)
@@messages.addMessagesAsHash(type,array)
end
def self.setMessagesAsHash(type,array)
@@messages.setMessagesAsHash(type,array)
end
def self.saveMessages(filename=nil)
@@messages.saveMessages(filename)
end
def self.loadMessageFile(filename)
@@messages.loadMessageFile(filename)
end
def self.get(type,id)
ret=@@messages.get(type,id)
if ret==""
ret=@@messagesFallback.get(type,id)
end
return ret
end
def self.getCount(type)
c1=@@messages.getCount(type)
c2=@@messagesFallback.getCount(type)
return c1>c2 ? c1 : c2
end
def self.getOriginal(type,id)
return @@messagesFallback.get(type,id)
end
def self.getFromHash(type,key)
@@messages.getFromHash(type,key)
end
def self.getFromMapHash(type,key)
@@messages.getFromMapHash(type,key)
end
end
def pbLoadMessages(file)
return MessageTypes.loadMessageFile(file)
end
def pbGetMessageCount(type)
return MessageTypes.getCount(type)
end
def pbGetMessage(type,id)
return MessageTypes.get(type,id)
end
def pbGetMessageFromHash(type,id)
return MessageTypes.getFromHash(type,id)
end
# Replaces first argument with a localized version and formats the other
# parameters by replacing {1}, {2}, etc. with those placeholders.
def _INTL(*arg)
begin
string=MessageTypes.getFromHash(MessageTypes::ScriptTexts,arg[0])
rescue
string=arg[0]
end
string=string.clone
for i in 1...arg.length
string.gsub!(/\{#{i}\}/,"#{arg[i]}")
end
return string
end
# Replaces first argument with a localized version and formats the other
# parameters by replacing {1}, {2}, etc. with those placeholders.
# This version acts more like sprintf, supports e.g. {1:d} or {2:s}
def _ISPRINTF(*arg)
begin
string=MessageTypes.getFromHash(MessageTypes::ScriptTexts,arg[0])
rescue
string=arg[0]
end
string=string.clone
for i in 1...arg.length
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%"+$1,arg[i])
}
end
return string
end
def _I(str)
return _MAPINTL($game_map.map_id,str)
end
def _MAPINTL(mapid,*arg)
string=MessageTypes.getFromMapHash(mapid,arg[0])
string=string.clone
for i in 1...arg.length
string.gsub!(/\{#{i}\}/,"#{arg[i]}")
end
return string
end
def _MAPISPRINTF(mapid,*arg)
string=MessageTypes.getFromMapHash(mapid,arg[0])
string=string.clone
for i in 1...arg.length
string.gsub!(/\{#{i}\:([^\}]+?)\}/) { |m|
next sprintf("%"+$1,arg[i])
}
end
return string
end

View File

@@ -0,0 +1,40 @@
module PBDebug
@@log = []
def self.logonerr
begin
yield
rescue
PBDebug.log("")
PBDebug.log("**Exception: #{$!.message}")
PBDebug.log("#{$!.backtrace.inspect}")
PBDebug.log("")
# if $INTERNAL
pbPrintException($!)
# end
PBDebug.flush
end
end
def self.flush
if $DEBUG && $INTERNAL && @@log.length>0
File.open("Data/debuglog.txt", "a+b") { |f| f.write("#{@@log}") }
end
@@log.clear
end
def self.log(msg)
if $DEBUG && $INTERNAL
@@log.push("#{msg}\r\n")
# if @@log.length>1024
PBDebug.flush
# end
end
end
def self.dump(msg)
if $DEBUG && $INTERNAL
File.open("Data/dumplog.txt", "a+b") { |f| f.write("#{msg}\r\n") }
end
end
end