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 if safeExists?("Data/PluginScripts.rxdata") plugin_scripts = load_data("Data/PluginScripts.rxdata") for plugin in plugin_scripts for script in plugin[2] if Time.now.to_i - t >= 5 t = Time.now.to_i Graphics.update end scr = Zlib::Inflate.inflate(script[1]).force_encoding(Encoding::UTF_8) pbAddRgssScriptTexts(texts,scr) end end end # Must add messages because this code is used by both game system and Editor MessageTypes.addMessagesAsHash(MessageTypes::ScriptTexts,texts) commonevents = load_data("Data/CommonEvents.rxdata") 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]}" 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 = pbLoadMapInfos 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.rxdata",id) 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]}" 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].ord==0xEF && line[1].ord==0xBB && line[2].ord==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 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 i0 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/,"<>") ret.gsub!(/\n/,"<>") ret.gsub!(/\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") ret.gsub!(/<>/,"\n") ret.gsub!(/<<\[>>/,"[") ret.gsub!(/<<\]>>/,"]") ret.gsub!(/<>/,"\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 nil_or_empty?(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 nil_or_empty?(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) hash=OrderedHash.new if !hash 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 RibbonNames = 25 RibbonDescriptions = 26 @@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