Advertisement
Guest User

Compiler

a guest
Sep 24th, 2014
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 126.65 KB | None | 0 0
  1. class Reset < Exception
  2. end
  3.  
  4.  
  5.  
  6. def pbGetExceptionMessage(e,script="")
  7.   emessage=e.message
  8.   if e.is_a?(Hangup)
  9.     emessage="The script is taking too long.  The game will restart."
  10.   elsif e.is_a?(Errno::ENOENT)
  11.     filename=emessage.sub("No such file or directory - ", "")
  12.     emessage="File #{filename} not found."
  13.   end
  14.   if emessage && !safeExists?("Game.rgssad") && !safeExists?("Game.rgss2a")
  15.     emessage=emessage.gsub(/uninitialized constant PBItems\:\:(\S+)/){
  16.        "The item '#{$1}' is not valid. Please add the item\r\nto the list of items in the editor. See the wiki for more information." }
  17.     emessage=emessage.gsub(/undefined method `(\S+?)' for PBItems\:Module/){
  18.       "The item '#{$1}' is not valid. Please add the item\r\nto the list of items in the editor. See the wiki for more information." }
  19.    emessage=emessage.gsub(/uninitialized constant PBTypes\:\:(\S+)/){
  20.       "The type '#{$1}' is not valid. Please add the type\r\nto the PBS/types.txt file." }
  21.    emessage=emessage.gsub(/undefined method `(\S+?)' for PBTypes\:Module/){
  22.       "The type '#{$1}' is not valid. Please add the type\r\nto the PBS/types.txt file." }
  23.     emessage=emessage.gsub(/uninitialized constant PBTrainers\:\:(\S+)$/){
  24.        "The trainer type '#{$1}' is not valid. Please add the trainer\r\nto the list of trainer types in the Editor. See the wiki for\r\nmore information." }
  25.     emessage=emessage.gsub(/undefined method `(\S+?)' for PBTrainers\:Module/){
  26.       "The trainer type '#{$1}' is not valid. Please add the trainer\r\nto the list of trainer types in the Editor. See the wiki for\r\nmore information." }
  27.    emessage=emessage.gsub(/uninitialized constant PBSpecies\:\:(\S+)$/){
  28.       "The Pokemon species '#{$1}' is not valid. Please\r\nadd the species to the PBS/pokemon.txt file.\r\nSee the wiki for more information." }
  29.    emessage=emessage.gsub(/undefined method `(\S+?)' for PBSpecies\:Module/){
  30.       "The Pokemon species '#{$1}' is not valid. Please\r\nadd the species to the PBS/pokemon.txt file.\r\nSee the wiki for more information." }
  31.   end
  32.  return emessage
  33. end
  34.  
  35. def pbPrintException(e)
  36.   emessage=pbGetExceptionMessage(e)
  37.   btrace=""
  38.   if e.backtrace
  39.     maxlength=$INTERNAL ? 25 : 10
  40.     e.backtrace[0,maxlength].each do |i|
  41.       btrace=btrace+"#{i}\r\n"
  42.     end
  43.   end
  44.   btrace.gsub!(/Section(\d+)/){$RGSS_SCRIPTS[$1.to_i][1]}
  45.   message="Exception: #{e.class}\r\nMessage: #{emessage}\r\n#{btrace}"
  46.   errorlog="errorlog.txt"
  47.   if (Object.const_defined?(:RTP) rescue false)
  48.     errorlog=RTP.getSaveFileName("errorlog.txt")
  49.   end
  50.   errorlogline=errorlog.sub(Dir.pwd+"\\","")
  51.   errorlogline=errorlogline.sub(Dir.pwd+"/","")
  52.   if errorlogline.length>20
  53.     errorlogline="\r\n"+errorlogline
  54.   end
  55.   File.open(errorlog,"ab"){|f| f.write(message) }
  56.   if !e.is_a?(Hangup)
  57.     print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nPress Ctrl+C to copy this message to the clipboard.")
  58.   end
  59. end
  60.  
  61. def pbCriticalCode
  62.   ret=0
  63.   begin
  64.     yield
  65.     ret=1
  66.     rescue Exception
  67.     e=$!
  68.     if e.is_a?(Reset) || e.is_a?(SystemExit)
  69.       raise
  70.     else
  71.       pbPrintException(e)
  72.       if e.is_a?(Hangup)
  73.         ret=2
  74.         raise Reset.new
  75.       end
  76.     end
  77.   end
  78.   return ret
  79. end
  80.  
  81.  
  82.  
  83. ####################
  84.  
  85. module FileLineData
  86.   @file=""
  87.   @linedata=""
  88.   @lineno=0
  89.   @section=nil
  90.   @key=nil
  91.   @value=nil
  92.  
  93.   def self.file
  94.     @file
  95.   end
  96.  
  97.   def self.file=(value)
  98.     @file=value
  99.   end
  100.  
  101.   def self.clear
  102.     @file=""
  103.     @linedata=""
  104.     @lineno=""
  105.     @section=nil
  106.     @key=nil
  107.     @value=nil
  108.   end
  109.  
  110.   def self.linereport
  111.     if @section
  112.       return _INTL("File {1}, section {2}, key {3}\r\n{4}\r\n",@file,@section,@key,@value)
  113.     else
  114.       return _INTL("File {1}, line {2}\r\n{3}\r\n",@file,@lineno,@linedata)
  115.     end
  116.   end
  117.  
  118.   def self.setSection(section,key,value)
  119.     @section=section
  120.     @key=key
  121.     if value && value.length>200
  122.       @value=_INTL("{1}...",value[0,200])
  123.     else
  124.       @value=!value ? "" : value.clone
  125.     end
  126.   end
  127.  
  128.   def self.setLine(line,lineno)
  129.     @section=nil
  130.     if line && line.length>200
  131.       @linedata=_INTL("{1}...",line[0,200])
  132.     else
  133.       @linedata=line
  134.     end
  135.     @lineno=lineno
  136.   end
  137. end
  138.  
  139.  
  140.  
  141. def findIndex(a)
  142.   index=-1
  143.   count=0
  144.   a.each {|i|
  145.      if yield i
  146.        index=count
  147.        break
  148.      end
  149.      count+=1
  150.   }
  151.   return index
  152. end
  153.  
  154. def prepline(line)
  155.   line.sub!(/\s*\#.*$/,"")
  156.   line.sub!(/\s+$/,"")
  157.   return line
  158. end
  159.  
  160. def csvfield!(str)
  161.   ret=""
  162.   str.sub!(/^\s*/,"")
  163.   if str[0,1]=="\""
  164.     str[0,1]=""
  165.     escaped=false
  166.     fieldbytes=0
  167.     str.scan(/./) do |s|
  168.       fieldbytes+=s.length
  169.       break if s=="\"" && !escaped
  170.       if s=="\\" && !escaped
  171.         escaped=true
  172.       else
  173.         ret+=s
  174.         escaped=false
  175.       end
  176.     end
  177.     str[0,fieldbytes]=""
  178.     if !str[/^\s*,/] && !str[/^\s*$/]
  179.       raise _INTL("Invalid quoted field (in: {1})\r\n{2}",str,FileLineData.linereport)
  180.     end
  181.     str[0,str.length]=$~.post_match
  182.   else
  183.     if str[/,/]
  184.       str[0,str.length]=$~.post_match
  185.       ret=$~.pre_match
  186.     else
  187.       ret=str.clone
  188.       str[0,str.length]=""
  189.     end
  190.     ret.gsub!(/\s+$/,"")
  191.   end
  192.   return ret
  193. end
  194.  
  195. def csvquote(str)
  196.   return "" if !str || str==""
  197.   if str[/[,\"]/] #|| str[/^\s/] || str[/\s$/] || str[/^#/]
  198.    str=str.gsub(/[\"]/,"\\\"")
  199.     str="\"#{str}\""
  200.   end
  201.   return str
  202. end
  203.  
  204. def csvBoolean!(str,line=-1)
  205.   field=csvfield!(str)
  206.   if field[/^1|[Tt][Rr][Uu][Ee]|[Yy][Ee][Ss]$/]
  207.     return true
  208.   elsif field[/^0|[Ff][Aa][Ll][Ss][Ee]|[Nn][Oo]$/]
  209.     return false
  210.   else
  211.     raise _INTL("Field {1} is not a Boolean value (true, false, 1, 0)\r\n{2}",field,FileLineData.linereport)
  212.     return false
  213.   end
  214. end
  215.  
  216. def csvPosInt!(str,line=-1)
  217.   ret=csvfield!(str)
  218.   if !ret[/^\d+$/]
  219.     raise _INTL("Field {1} is not a positive integer\r\n{2}",ret,FileLineData.linereport)
  220.   end
  221.   return ret.to_i
  222. end
  223.  
  224. def csvInt!(str,line=-1)
  225.   ret=csvfield!(str)
  226.   if !ret[/^\-?\d+$/]
  227.     raise _INTL("Field {1} is not an integer\r\n{2}",ret,FileLineData.linereport)
  228.   end
  229.   return ret.to_i
  230. end
  231.  
  232. def csvFloat!(str,key,section)
  233.   ret=csvfield!(str)
  234.   return Float(ret) rescue raise _INTL("Field {1} is not a number\r\n{2}",ret,FileLineData.linereport)
  235. end
  236.  
  237. def intSize(value)
  238.   return 1 if value<0x80
  239.   return 2 if value<0x4000
  240.   return 3 if value<0x200000
  241.   return 4 if value<0x10000000
  242.   return 5
  243. end
  244.  
  245. def strSize(str)
  246.   return str.length+intSize(str.length)
  247. end
  248.  
  249. def encodeInt(strm,value)
  250.   num=0
  251.   loop do
  252.     if value<0x80
  253.       strm.fputb(value)
  254.       return num+1
  255.     end
  256.     strm.fputb(0x80|(value&0x7F))
  257.     value>>=7
  258.     num+=1
  259.   end
  260. end
  261.  
  262. def decodeInt(strm)
  263.   bits=0
  264.   curbyte=0
  265.   ret=0
  266.   begin
  267.     curbyte=strm.fgetb
  268.     ret+=(curbyte&0x7F)<<bits
  269.     bits+=7
  270.   end while(((curbyte&0x80)>0)&&bits<0x1d)
  271.   return ret
  272. end
  273.  
  274. def encodeString(strm,str)
  275.   encodeInt(strm,str.length)
  276.   strm.write(str)
  277. end
  278.  
  279. def decodeString(strm)
  280.   len=decodeInt(strm)
  281.   return strm.read(len)
  282. end
  283.  
  284.  
  285.  
  286. class SerialRecord < Array
  287.   def bytesize
  288.     return SerialRecord.bytesize(self)
  289.   end
  290.  
  291.   def encode(strm)
  292.     return SerialRecord.encode(self,strm)
  293.   end
  294.  
  295.   def self.bytesize(arr)
  296.     ret=0
  297.     return 0 if !arr
  298.     for field in arr
  299.       if field==nil || field==true || field==false
  300.         ret+=1
  301.       elsif field.is_a?(String)
  302.         ret+=strSize(field)+1
  303.       elsif field.is_a?(Numeric)
  304.         ret+=intSize(field)+1
  305.       end
  306.     end
  307.     return ret
  308.   end
  309.  
  310.   def self.encode(arr,strm)
  311.     return if !arr
  312.     for field in arr
  313.       if field==nil
  314.         strm.write("0")
  315.       elsif field==true
  316.         strm.write("T")
  317.       elsif field==false
  318.         strm.write("F")
  319.       elsif field.is_a?(String)
  320.         strm.write("\"")
  321.         encodeString(strm,field)
  322.       elsif field.is_a?(Numeric)
  323.         strm.write("i")
  324.         encodeInt(strm,field)
  325.       end
  326.     end
  327.   end
  328.  
  329.   def self.decode(strm,offset,length)
  330.     ret=SerialRecord.new
  331.     strm.pos=offset
  332.     while strm.pos<offset+length
  333.       datatype=strm.read(1)
  334.       case datatype
  335.         when "0"
  336.           ret.push(nil)
  337.         when "T"
  338.           ret.push(true)
  339.         when "F"
  340.           ret.push(false)
  341.         when "\""
  342.           ret.push(decodeString(strm))
  343.         when "i"
  344.           ret.push(decodeInt(strm))
  345.       end
  346.     end
  347.     return ret
  348.   end
  349. end
  350.  
  351.  
  352.  
  353. def readSerialRecords(filename)
  354.   ret=[]
  355.   pbRgssOpen(filename,"rb"){|file|
  356.      numrec=file.fgetdw>>3
  357.      curpos=0
  358.      for i in 0...numrec
  359.        file.pos=curpos
  360.        offset=file.fgetdw
  361.        length=file.fgetdw
  362.        record=SerialRecord.decode(file,offset,length)
  363.        ret.push(record)
  364.        curpos+=8
  365.      end  
  366.   }
  367.   return ret
  368. end
  369.  
  370.  
  371.  
  372. class ItemList
  373.   include Enumerable
  374.  
  375.   def initialize
  376.     @list=[]
  377.   end
  378.  
  379.   def []=(x,v); @list[x]=v; end
  380.  
  381.   def [](x)
  382.     if !@list[x]
  383.       defrecord=SerialRecord.new
  384.       defrecord.push(0)
  385.       defrecord.push("????????")
  386.       defrecord.push(0)
  387.       defrecord.push(0)
  388.       defrecord.push("????????")
  389.       @list[x]=defrecord
  390.       return defrecord
  391.     end
  392.     return @list[x]
  393.   end
  394.  
  395.   def length; @list.length; end
  396.  
  397.   def each
  398.     for i in 0...self.length
  399.       yield self[i]
  400.     end
  401.   end
  402. end
  403.  
  404.  
  405.  
  406. def readSerialRecords(filename)
  407.   ret=[]
  408.   if !pbRgssExists?(filename)
  409.     return ret
  410.   end
  411.   pbRgssOpen(filename,"rb"){|file|
  412.      numrec=file.fgetdw>>3
  413.      curpos=0
  414.      for i in 0...numrec
  415.        file.pos=curpos
  416.        offset=file.fgetdw
  417.        length=file.fgetdw
  418.        record=SerialRecord.decode(file,offset,length)
  419.        ret.push(record)
  420.        curpos+=8
  421.      end
  422.   }
  423.   return ret
  424. end
  425.  
  426. def readItemList(filename)
  427.   ret=ItemList.new
  428.   if !pbRgssExists?(filename)
  429.     return ret
  430.   end
  431.   pbRgssOpen(filename,"rb"){|file|
  432.      numrec=file.fgetdw>>3
  433.      curpos=0
  434.      for i in 0...numrec
  435.        file.pos=curpos
  436.        offset=file.fgetdw
  437.        length=file.fgetdw
  438.        record=SerialRecord.decode(file,offset,length)
  439.        ret[record[0]]=record
  440.        curpos+=8
  441.      end
  442.   }
  443.   return ret
  444. end
  445.  
  446. def writeSerialRecords(filename,records)
  447.   File.open(filename,"wb"){|file|
  448.      totalsize=records.length*8
  449.      for record in records
  450.        file.fputdw(totalsize)
  451.        bytesize=record.bytesize
  452.        file.fputdw(bytesize)
  453.        totalsize+=bytesize
  454.      end
  455.      for record in records
  456.        record.encode(file)
  457.      end
  458.   }
  459. end
  460.  
  461. def pbGetCsvRecord(rec,lineno,schema)
  462.   record=[]
  463.   repeat=false
  464.   if schema[1][0,1]=="*"
  465.     repeat=true
  466.     start=1
  467.   else
  468.     repeat=false
  469.     start=0
  470.   end
  471.   begin
  472.     for i in start...schema[1].length
  473.       chr=schema[1][i,1]
  474.       case chr
  475.         when "u"
  476.           record.push(csvPosInt!(rec,lineno))
  477.         when "v"
  478.           field=csvPosInt!(rec,lineno)
  479.           raise _INTL("Field '{1}' must be greater than 0\r\n{2}",field,FileLineData.linereport) if field==0
  480.           record.push(field)
  481.         when "i"
  482.           record.push(csvInt!(rec,lineno))
  483.         when "U", "I"
  484.           field=csvfield!(rec)
  485.           if field==""
  486.             record.push(nil)
  487.           elsif !field[/^\d+$/]
  488.             raise _INTL("Field '{1}' must be 0 or greater\r\n{2}",field,FileLineData.linereport)
  489.           else
  490.             record.push(field.to_i)
  491.           end
  492.         when "x"
  493.           field=csvfield!(rec)    
  494.           if !field[/^[A-Fa-f0-9]+$/]
  495.             raise _INTL("Field '{1}' is not a hexadecimal number\r\n{2}",field,FileLineData.linereport)
  496.           end
  497.           record.push(field.hex)
  498.         when "s"
  499.           record.push(csvfield!(rec))
  500.         when "S"
  501.           field=csvfield!(rec)
  502.           if field==""
  503.             record.push(nil)
  504.           else
  505.             record.push(field)
  506.           end
  507.         when "n" # Name
  508.           field=csvfield!(rec)
  509.           if !field[/^(?![0-9])\w+$/]
  510.             raise _INTL("Field '{1}' must contain only letters, digits, and\r\nunderscores and can't begin with a number.\r\n{2}",field,FileLineData.linereport)
  511.           end
  512.           record.push(field)
  513.         when "N" # Optional name
  514.           field=csvfield!(rec)
  515.           if field==""
  516.             record.push(nil)
  517.           else
  518.             if !field[/^(?![0-9])\w+$/]
  519.               raise _INTL("Field '{1}' must contain only letters, digits, and\r\nunderscores and can't begin with a number.\r\n{2}",field,FileLineData.linereport)
  520.             end
  521.             record.push(field)
  522.           end
  523.         when "b"
  524.           record.push(csvBoolean!(rec,lineno))
  525.         when "e"
  526.           record.push(csvEnumField!(rec,schema[2+i-start],"",FileLineData.linereport))
  527.       end
  528.     end
  529.     break if repeat && rec==""
  530.   end while repeat
  531.   return (schema[1].length==1) ? record[0] : record
  532. end
  533.  
  534. def pbWriteCsvRecord(record,file,schema)
  535.   if !record.is_a?(Array)
  536.     rec=[record]
  537.   else
  538.     rec=record.clone
  539.   end
  540.   for i in 0...schema[1].length
  541.     chr=schema[1][i,1]
  542.     file.write(",") if i>0
  543.     if rec[i].nil?
  544.       # do nothing
  545.     elsif rec[i].is_a?(String)
  546.       file.write(csvquote(rec[i]))
  547.     elsif rec[i]==true
  548.       file.write("true")
  549.     elsif rec[i]==false
  550.       file.write("false")
  551.     elsif rec[i].is_a?(Numeric)
  552.       case chr
  553.         when "e"
  554.           enumer=schema[2+i]
  555.           if enumer.is_a?(Array)
  556.             file.write(enumer[rec[i]])
  557.           elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
  558.             mod=Object.const_get(enumer.to_sym)
  559.             if enumer.to_s=="PBTrainers" && !mod.respond_to?("getCount")
  560.               file.write((getConstantName(mod,rec[i]) rescue pbGetTrainerConst(rec[i])))
  561.             else
  562.               file.write(getConstantName(mod,rec[i]))
  563.             end
  564.           elsif enumer.is_a?(Module)
  565.             file.write(getConstantName(enumer,rec[i]))
  566.           elsif enumer.is_a?(Hash)
  567.             for key in enumer.keys
  568.               if enumer[key]==rec[i]
  569.                 file.write(key)
  570.                 break
  571.               end
  572.             end
  573.           end
  574.         else
  575.           file.write(rec[i].inspect)
  576.       end
  577.     else
  578.       file.write(rec[i].inspect)
  579.     end
  580.   end
  581.   return record
  582. end
  583.  
  584. def pbEachCommentedLine(f)
  585.   lineno=1
  586.   f.each_line {|line|
  587.      if lineno==1&&line[0]==0xEF&&line[1]==0xBB&&line[2]==0xBF
  588.        line=line[3,line.length-3]
  589.      end
  590.      if !line[/^\#/] && !line[/^\s*$/]
  591.        yield line, lineno
  592.      end
  593.      lineno+=1
  594.   }
  595. end
  596.  
  597. def pbEachPreppedLine(f)
  598.   lineno=1
  599.   f.each_line {|line|
  600.      if lineno==1&&line[0]==0xEF&&line[1]==0xBB&&line[2]==0xBF
  601.        line=line[3,line.length-3]
  602.      end
  603.      line=prepline(line)
  604.      if !line[/^\#/] && !line[/^\s*$/]
  605.        yield line, lineno
  606.      end
  607.      lineno+=1
  608.   }
  609. end
  610.  
  611. def pbCompilerEachCommentedLine(filename)
  612.   File.open(filename,"rb"){|f|
  613.      FileLineData.file=filename
  614.      lineno=1
  615.      f.each_line {|line|
  616.         if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  617.           line=line[3,line.length-3]
  618.         end
  619.         if !line[/^\#/] && !line[/^\s*$/]
  620.           FileLineData.setLine(line,lineno)
  621.           yield line, lineno
  622.         end
  623.         lineno+=1
  624.      }
  625.   }
  626. end
  627.  
  628. def pbCompilerEachPreppedLine(filename)
  629.   File.open(filename,"rb"){|f|
  630.      FileLineData.file=filename
  631.      lineno=1
  632.      f.each_line {|line|
  633.         if lineno==1&&line[0]==0xEF&&line[1]==0xBB&&line[2]==0xBF
  634.           line=line[3,line.length-3]
  635.         end
  636.         line=prepline(line)
  637.         if !line[/^\#/] && !line[/^\s*$/]
  638.           FileLineData.setLine(line,lineno)
  639.           yield line, lineno
  640.         end
  641.         lineno+=1
  642.      }
  643.   }
  644. end
  645.  
  646. def pbCompileShadowMoves
  647.   sections=[]
  648.   if File.exists?("PBS/shadowmoves.txt")
  649.     pbCompilerEachCommentedLine("PBS/shadowmoves.txt"){|line,lineno|
  650.        if line[ /^([^=]+)=(.*)$/ ]
  651.          key=$1
  652.          value=$2
  653.          value=value.split(",")
  654.          species=parseSpecies(key)
  655.          moves=[]
  656.          for i in 0...[4,value.length].min
  657.            moves.push((parseMove(value[i]) rescue nil))
  658.          end
  659.          moves.compact!
  660.          sections[species]=moves if moves.length>0
  661.        end
  662.     }
  663.   end
  664.   save_data(sections,"Data/shadowmoves.dat")
  665. end
  666.  
  667. def pbCompileBTTrainers(filename)
  668.   sections=[]
  669.   btTrainersRequiredTypes={
  670.      "Type"=>[0,"e",PBTrainers],
  671.      "Name"=>[1,"s"],
  672.      "BeginSpeech"=>[2,"s"],
  673.      "EndSpeechWin"=>[3,"s"],
  674.      "EndSpeechLose"=>[4,"s"],
  675.      "PokemonNos"=>[5,"*u"]
  676.   }
  677.   requiredtypes=btTrainersRequiredTypes
  678.   trainernames=[]
  679.   beginspeech=[]
  680.   endspeechwin=[]
  681.   endspeechlose=[]
  682.   if safeExists?(filename)
  683.     File.open(filename,"rb"){|f|
  684.        FileLineData.file=filename
  685.        pbEachFileSectionEx(f){|section,name|
  686.           rsection=[]
  687.           for key in section.keys
  688.             FileLineData.setSection(name,key,section[key])
  689.             schema=requiredtypes[key]
  690.             next if !schema
  691.             record=pbGetCsvRecord(section[key],0,schema)
  692.             rsection[schema[0]]=record  
  693.           end
  694.           trainernames.push(rsection[1])
  695.           beginspeech.push(rsection[2])
  696.           endspeechwin.push(rsection[3])
  697.           endspeechlose.push(rsection[4])
  698.           sections.push(rsection)
  699.        }
  700.     }
  701.   end
  702.   MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
  703.   MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
  704.   MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
  705.   MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
  706.   return sections
  707. end
  708.  
  709. def pbCompileTownMap
  710.   nonglobaltypes={
  711.      "Name"=>[0,"s"],
  712.      "Filename"=>[1,"s"],
  713.      "Point"=>[2,"uussUUUU"]
  714.   }
  715.   currentmap=-1
  716.   rgnnames=[]
  717.   placenames=[]
  718.   placedescs=[]
  719.   sections=[]
  720.   pbCompilerEachCommentedLine("PBS/townmap.txt"){|line,lineno|
  721.      if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
  722.        currentmap=$~[1].to_i
  723.        sections[currentmap]=[]
  724.      else
  725.        if currentmap<0
  726.          raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
  727.        end
  728.        if !line[/^\s*(\w+)\s*=\s*(.*)$/]
  729.          raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
  730.        end
  731.        settingname=$~[1]
  732.        schema=nonglobaltypes[settingname]
  733.        if schema
  734.          record=pbGetCsvRecord($~[2],lineno,schema)
  735.          if settingname=="Name"
  736.            rgnnames[currentmap]=record    
  737.          elsif settingname=="Point"
  738.            placenames.push(record[2])
  739.            placedescs.push(record[3])
  740.            sections[currentmap][schema[0]]=[] if !sections[currentmap][schema[0]]
  741.            sections[currentmap][schema[0]].push(record)
  742.          else   # Filename
  743.            sections[currentmap][schema[0]]=record
  744.          end
  745.        end
  746.      end
  747.   }
  748.   File.open("Data/townmap.dat","wb"){|f|
  749.      Marshal.dump(sections,f)
  750.   }
  751.   MessageTypes.setMessages(
  752.      MessageTypes::RegionNames,rgnnames
  753.   )
  754.   MessageTypes.setMessagesAsHash(
  755.      MessageTypes::PlaceNames,placenames
  756.   )
  757.   MessageTypes.setMessagesAsHash(
  758.      MessageTypes::PlaceDescriptions,placedescs
  759.   )
  760. end
  761.  
  762.  
  763.  
  764. class PBTrainers; end
  765.  
  766.  
  767.  
  768. def pbCompileMetadata
  769.   sections=[]
  770.   currentmap=-1
  771.   pbCompilerEachCommentedLine("PBS/metadata.txt") {|line,lineno|
  772.      if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
  773.        sectionname=$~[1]
  774.        if currentmap==0
  775.          if sections[currentmap][MetadataHome]==nil
  776.            raise _INTL("The entry Home is required in metadata.txt section [{1}]",sectionname)
  777.          end
  778.          if sections[currentmap][MetadataPlayerA]==nil
  779.            raise _INTL("The entry PlayerA is required in metadata.txt section [{1}]",sectionname)
  780.          end
  781.        end
  782.        currentmap=sectionname.to_i
  783.        sections[currentmap]=[]
  784.      else
  785.        if currentmap<0
  786.          raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
  787.        end
  788.        if !line[/^\s*(\w+)\s*=\s*(.*)$/]
  789.          raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
  790.        end
  791.        matchData=$~
  792.        schema=nil
  793.        FileLineData.setSection(currentmap,matchData[1],matchData[2])
  794.        if currentmap==0
  795.          schema=PokemonMetadata::GlobalTypes[matchData[1]]
  796.        else
  797.          schema=PokemonMetadata::NonGlobalTypes[matchData[1]]
  798.        end
  799.        if schema
  800.          record=pbGetCsvRecord(matchData[2],lineno,schema)
  801.          sections[currentmap][schema[0]]=record
  802.        end
  803.      end
  804.   }
  805.   File.open("Data/metadata.dat","wb"){|f|
  806.      Marshal.dump(sections,f)
  807.   }
  808. end
  809.  
  810. def pbCompileItems
  811.   records=[]
  812.   constants=""
  813.   itemnames=[]
  814.   itemdescs=[]
  815.   maxValue=0
  816.   pbCompilerEachCommentedLine("PBS/items.txt"){|line,lineno|
  817.      linerecord=pbGetCsvRecord(line,lineno,[0,"vnsuusuuUN"])
  818.      record=SerialRecord.new
  819.      record[ITEMID]        = linerecord[0]
  820.      constant=linerecord[1]
  821.      constants+="#{constant}=#{record[0]}\r\n"
  822.      record[ITEMNAME]      = linerecord[2]
  823.      itemnames[record[0]]=linerecord[2]
  824.      record[ITEMPOCKET]    = linerecord[3]
  825.      record[ITEMPRICE]     = linerecord[4]
  826.      record[ITEMDESC]      = linerecord[5]
  827.      itemdescs[record[0]]=linerecord[5]
  828.      record[ITEMUSE]       = linerecord[6]
  829.      record[ITEMBATTLEUSE] = linerecord[7]
  830.      record[ITEMTYPE]      = linerecord[8]
  831.      if linerecord[9]!="" && linerecord[9]
  832.        record[ITEMMACHINE] = parseMove(linerecord[9])
  833.      else
  834.        record[ITEMMACHINE] = 0
  835.      end
  836.      maxValue=[maxValue,record[0]].max
  837.      records.push(record)
  838.   }
  839.   MessageTypes.setMessages(MessageTypes::Items,itemnames)
  840.   MessageTypes.setMessages(MessageTypes::ItemDescriptions,itemdescs)
  841.   writeSerialRecords("Data/items.dat",records)
  842.   code="class PBItems\r\n#{constants}"
  843.   code+="\r\ndef PBItems.getName(id)\r\nreturn pbGetMessage(MessageTypes::Items,id)\r\nend\r\n"
  844.   code+="\r\ndef PBItems.getCount\r\nreturn #{records.length}\r\nend\r\n"
  845.   code+="\r\ndef PBItems.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  846.   eval(code)
  847.   pbAddScript(code,"PBItems")
  848.   Graphics.update
  849. end
  850.  
  851. def pbCompileConnections
  852.   records=[]
  853.   constants=""
  854.   itemnames=[]
  855.   pbCompilerEachPreppedLine("PBS/connections.txt"){|line,lineno|
  856.      hashenum={
  857.         "N"=>"N","North"=>"N",
  858.         "E"=>"E","East"=>"E",
  859.         "S"=>"S","South"=>"S",
  860.         "W"=>"W","West"=>"W"
  861.      }
  862.      record=[]
  863.      thisline=line.dup
  864.      record.push(csvInt!(thisline,lineno))
  865.      record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
  866.      record.push(csvInt!(thisline,lineno))
  867.      record.push(csvInt!(thisline,lineno))
  868.      record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
  869.      record.push(csvInt!(thisline,lineno))          
  870.      if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[0])) &&
  871.         !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[0]))
  872.        print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[0],FileLineData.linereport)
  873.      end
  874.      if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[3])) &&
  875.         !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[3]))
  876.        print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[3],FileLineData.linereport)
  877.      end
  878.      case record[1]
  879.        when "N"
  880.          raise _INTL("North side of first map must connect with south side of second map\r\n{1}",FileLineData.linereport) if record[4]!="S"
  881.        when "S"
  882.          raise _INTL("South side of first map must connect with north side of second map\r\n{1}",FileLineData.linereport) if record[4]!="N"
  883.        when "E"
  884.          raise _INTL("East side of first map must connect with west side of second map\r\n{1}",FileLineData.linereport) if record[4]!="W"
  885.        when "W"
  886.          raise _INTL("West side of first map must connect with east side of second map\r\n{1}",FileLineData.linereport) if record[4]!="E"
  887.      end
  888.      records.push(record)
  889.   }
  890.   save_data(records,"Data/connections.dat")
  891.   Graphics.update
  892. end
  893.  
  894. def strsplit(str,re)
  895.   ret=[]
  896.   tstr=str
  897.   while re=~tstr
  898.     ret[ret.length]=$~.pre_match
  899.     tstr=$~.post_match
  900.   end
  901.   ret[ret.length]=tstr if ret.length
  902.   return ret
  903. end
  904.  
  905. def canonicalize(c)
  906.   csplit=strsplit(c,/[\/\\]/)
  907.   pos=-1
  908.   ret=[]
  909.   retstr=""
  910.   for x in csplit
  911.     if x=="."
  912.     elsif x==".."
  913.       ret.delete_at(pos) if pos>=0
  914.       pos-=1
  915.     else
  916.       ret.push(x)
  917.       pos+=1
  918.     end
  919.   end
  920.   for i in 0...ret.length
  921.     retstr+="/" if i>0
  922.     retstr+=ret[i]
  923.   end
  924.   return retstr
  925. end
  926.  
  927. def pbGetConst(mod,item,err)
  928.   isdef=false
  929.   begin
  930.     isdef=mod.const_defined?(item.to_sym)
  931.     rescue
  932.     raise sprintf(err,item)
  933.   end
  934.   raise sprintf(err,item) if !isdef
  935.   return mod.const_get(item.to_sym)
  936. end
  937.  
  938. def parseItem(item)
  939.   clonitem=item.upcase
  940.   clonitem.sub!(/^\s*/){}
  941.   clonitem.sub!(/\s*$/){}
  942.   return pbGetConst(PBItems,clonitem,
  943.      _INTL("Undefined item constant name: %s\r\nName must consist only of letters, numbers, and\r\nunderscores and can't begin with a number.\r\nMake sure the item is defined in\r\nPBS/items.txt.\r\n{1}",
  944.      FileLineData.linereport))
  945. end
  946.  
  947. def parseSpecies(item)
  948.   clonitem=item.upcase
  949.   clonitem.gsub!(/^[\s\n]*/){}
  950.   clonitem.gsub!(/[\s\n]*$/){}
  951.   clonitem="NIDORANmA" if clonitem=="NIDORANMA"
  952.   clonitem="NIDORANfE" if clonitem=="NIDORANFE"
  953.   return pbGetConst(PBSpecies,clonitem,_INTL("Undefined species constant name: [%s]\r\nName must consist only of letters, numbers, and\r\nunderscores and can't begin with a number.\r\nMake sure the name is defined in\r\nPBS/pokemon.txt.\r\n{1}",FileLineData.linereport))
  954. end
  955.  
  956. def parseMove(item)
  957.   clonitem=item.upcase
  958.   clonitem.sub!(/^\s*/){}
  959.   clonitem.sub!(/\s*$/){}
  960.   return pbGetConst(PBMoves,clonitem,_INTL("Undefined move constant name: %s\r\nName must consist only of letters, numbers, and\r\nunderscores and can't begin with a number.\r\nMake sure the name is defined in\r\nPBS/moves.txt.\r\n{1}",FileLineData.linereport))
  961. end
  962.  
  963. def parseNature(item)
  964.   clonitem=item.upcase
  965.   clonitem.sub!(/^\s*/){}
  966.   clonitem.sub!(/\s*$/){}
  967.   return pbGetConst(PBNatures,clonitem,_INTL("Undefined nature constant name: %s\r\nName must consist only of letters, numbers, and\r\nunderscores and can't begin with a number.\r\nMake sure the name is defined in\r\nthe script section PBNatures.\r\n{1}",FileLineData.linereport))
  968. end
  969.  
  970. def parseTrainer(item)
  971.   clonitem=item.clone
  972.   clonitem.sub!(/^\s*/){}
  973.   clonitem.sub!(/\s*$/){}
  974.   return pbGetConst(PBTrainers,clonitem,_INTL("Undefined Trainer constant name: %s\r\nName must consist only of letters, numbers, and\r\nunderscores and can't begin with a number.\r\nIn addition, the name must be defined\r\nin trainertypes.txt.\r\n{1}",FileLineData.linereport))
  975. end
  976.  
  977. def pbFindScript(a,name)
  978.   a.each{|i|
  979.      next if !i
  980.      return i if i[1]==name
  981.   }
  982.   return nil
  983. end
  984.  
  985. def pbAddScript(script,sectionname)
  986.   begin
  987.     scripts=load_data("Data/Constants.rxdata")
  988.     scripts=[] if !scripts
  989.   rescue
  990.     scripts=[]
  991.   end
  992.   s=pbFindScript(scripts,sectionname)
  993.   if s
  994.     s[2]=Zlib::Deflate.deflate("#{script}\r\n")
  995.   else
  996.     scripts.push([rand(100000000),sectionname,Zlib::Deflate.deflate("#{script}\r\n")])
  997.   end
  998.   save_data(scripts,"Data/Constants.rxdata")
  999. end
  1000.  
  1001. def pbCompileEncounters
  1002.   lines=[]
  1003.   linenos=[]
  1004.   FileLineData.file="PBS/encounters.txt"
  1005.   File.open("PBS/encounters.txt","rb"){|f|
  1006.      lineno=1
  1007.      f.each_line {|line|
  1008.         line=prepline(line)
  1009.         if line.length!=0
  1010.           lines[lines.length]=line
  1011.           linenos[linenos.length]=lineno
  1012.         end
  1013.         lineno+=1
  1014.      }
  1015.   }
  1016.   encounters={}
  1017.   thisenc=nil
  1018.   lastenc=-1
  1019.   lastenclen=0
  1020.   needdensity=false
  1021.   lastmapid=-1
  1022.   i=0;
  1023.   while i<lines.length
  1024.     line=lines[i]
  1025.     FileLineData.setLine(line,linenos[i])
  1026.     mapid=line[/^\d+$/]
  1027.     if mapid
  1028.       lastmapid=mapid
  1029.       if thisenc && (thisenc[1][EncounterTypes::Land] ||
  1030.                      thisenc[1][EncounterTypes::LandMorning] ||
  1031.                      thisenc[1][EncounterTypes::LandDay] ||
  1032.                      thisenc[1][EncounterTypes::BugContest] ||
  1033.                      thisenc[1][EncounterTypes::LandNight]) &&
  1034.                      thisenc[1][EncounterTypes::Cave]
  1035.         raise _INTL("Can't define both Land and Cave encounters in the same area (map ID {1})",mapid)
  1036.       end
  1037.       thisenc=[EncounterTypes::EnctypeDensities.clone,[]]
  1038.       encounters[mapid.to_i]=thisenc
  1039.       needdensity=true
  1040.       i+=1
  1041.       next
  1042.     end
  1043.     enc=findIndex(EncounterTypes::Names){|val| val==line}
  1044.     if enc>=0
  1045.       needdensity=false
  1046.       enclines=EncounterTypes::EnctypeChances[enc].length
  1047.       encarray=[]
  1048.       j=i+1; k=0
  1049.       while j<lines.length && k<enclines
  1050.         line=lines[j]
  1051.         FileLineData.setLine(lines[j],linenos[j])
  1052.         splitarr=strsplit(line,/\s*,\s*/)
  1053.         if !splitarr || splitarr.length<2
  1054.           raise _INTL("In encounters.txt, expected a species entry line,\r\ngot \"{1}\" instead (probably too few entries in an encounter type).\r\nPlease check the format of the section numbered {2},\r\nwhich is just before this line.\r\n{3}",
  1055.              line,lastmapid,FileLineData.linereport)
  1056.         end
  1057.         splitarr[2]=splitarr[1] if splitarr.length==2
  1058.         splitarr[1]=splitarr[1].to_i
  1059.         splitarr[2]=splitarr[2].to_i
  1060.         maxlevel=PBExperience::MAXLEVEL
  1061.         if splitarr[1]<=0 || splitarr[1]>maxlevel
  1062.           raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[1],FileLineData.linereport)
  1063.         end
  1064.         if splitarr[2]<=0 || splitarr[2]>maxlevel
  1065.           raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[2],FileLineData.linereport)
  1066.         end
  1067.         if splitarr[1]>splitarr[2]
  1068.           raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}",line,FileLineData.linereport)
  1069.         end
  1070.         splitarr[0]=parseSpecies(splitarr[0])
  1071.         linearr=splitarr
  1072.         encarray.push(linearr)
  1073.         thisenc[1][enc]=encarray
  1074.         j+=1
  1075.         k+=1
  1076.       end
  1077.       if j==lines.length && k<enclines
  1078.          raise _INTL("Reached end of file unexpectedly. There were too few entries in the last section, expected {1} entries.\r\nPlease check the format of the section numbered {2}.\r\n{3}",
  1079.             enclines,lastmapid,FileLineData.linereport)
  1080.       end
  1081.       i=j
  1082.     elsif needdensity
  1083.       needdensity=false
  1084.       nums=strsplit(line,/,/)
  1085.       if nums && nums.length>=3
  1086.         for j in 0...EncounterTypes::EnctypeChances.length
  1087.           next if !EncounterTypes::EnctypeChances[j] ||
  1088.                   EncounterTypes::EnctypeChances[j].length==0
  1089.           next if EncounterTypes::EnctypeCompileDens[j]==0
  1090.           thisenc[0][j]=nums[EncounterTypes::EnctypeCompileDens[j]-1].to_i
  1091.         end
  1092.       else
  1093.         raise _INTL("Wrong syntax for densities in encounters.txt; got \"{1}\"\r\n{2}",line,FileLineData.linereport)
  1094.       end
  1095.       i+=1
  1096.     else
  1097.       raise _INTL("Undefined encounter type {1}, expected one of the following:\r\n{2}\r\n{3}",
  1098.          line,EncounterTypes::Names.inspect,FileLineData.linereport)
  1099.     end
  1100.   end
  1101.   save_data(encounters,"Data/encounters.dat")
  1102. end
  1103.  
  1104. def pbCheckByte(x,valuename)
  1105.   if x<0 || x>255
  1106.     raise _INTL("The value \"{1}\" must be from 0 through 255 (0x00-0xFF in hex), got a value of {2}\r\n{3}",
  1107.        valuename,x,FileLineData.linereport)
  1108.   end
  1109. end
  1110.  
  1111. def pbCheckWord(x,valuename)
  1112.   if x<0 || x>65535
  1113.     raise _INTL("The value \"{1}\" must be from 0 through 65535 (0x0000-0xFFFF in hex), got a value of {2}\r\n{3}",
  1114.        valuename,x,FileLineData.linereport)
  1115.   end
  1116. end
  1117.  
  1118. def pbCheckSignedWord(x,valuename)
  1119.   if x<-32768 || x>32767
  1120.     raise _INTL("The value \"{1}\" must be from -32768 through 32767, got a value of {2}\r\n{3}",
  1121.        valuename,x,FileLineData.linereport)
  1122.   end
  1123. end
  1124.  
  1125. def pbCheckSignedByte(x,valuename)
  1126.   if x<-128 || x>127
  1127.     raise _INTL("The value \"{1}\" must be from -128 through 127, got a value of {2}\r\n{3}",
  1128.        valuename,x,FileLineData.linereport)
  1129.   end
  1130. end
  1131.  
  1132.  
  1133. class PBMoveDataOld
  1134.   attr_reader :function,:basedamage,:type,:accuracy
  1135.   attr_reader :totalpp,:addlEffect,:target,:priority
  1136.   attr_reader :flags
  1137.   attr_reader :contestType,:category
  1138.  
  1139.   def initialize(moveid)
  1140.     movedata=pbRgssOpen("Data/rsattacks.dat")
  1141.     movedata.pos=moveid*9
  1142.     @function=movedata.fgetb
  1143.     @basedamage=movedata.fgetb
  1144.     @type=movedata.fgetb
  1145.     @accuracy=movedata.fgetb
  1146.     @totalpp=movedata.fgetb
  1147.     @addlEffect=movedata.fgetb
  1148.     @target=movedata.fgetb
  1149.     @priority=movedata.fgetsb
  1150.     @flags=movedata.fgetb
  1151.     movedata.close
  1152.   end
  1153.  
  1154.   def category
  1155.     return 2 if @basedamage==0
  1156.     return @type<10 ? 0 : 1
  1157.   end
  1158. end
  1159.  
  1160.  
  1161.  
  1162. def pbCompileMoves
  1163.   records=[]
  1164.   movenames=[]
  1165.   movedescs=[]
  1166.   movedata=[]
  1167.   maxValue=0
  1168.   haveRsAttacks=pbRgssExists?("Data/rsattacks.dat")
  1169.   pbCompilerEachPreppedLine("PBS/moves.txt"){|line,lineno|
  1170.      thisline=line.clone
  1171.      record=[]
  1172.      flags=0
  1173.      begin
  1174.        record=pbGetCsvRecord(line,lineno,[0,"vnsxueeuuuxises",
  1175.           nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"],
  1176.           nil,nil,nil,nil,nil,nil,["Cool","Beauty","Cute","Smart","Tough"],nil
  1177.        ])
  1178.        pbCheckWord(record[3],_INTL("Function code"))
  1179.        flags|=1 if record[12][/a/]
  1180.        flags|=2 if record[12][/b/]
  1181.        flags|=4 if record[12][/c/]
  1182.        flags|=8 if record[12][/d/]
  1183.        flags|=16 if record[12][/e/]
  1184.        flags|=32 if record[12][/f/]
  1185.        flags|=64 if record[12][/g/]
  1186.        flags|=128 if record[12][/h/]
  1187.        flags|=256 if record[12][/i/]
  1188.        flags|=512 if record[12][/j/]
  1189.        flags|=1024 if record[12][/k/]
  1190.        flags|=2048 if record[12][/l/]
  1191.        flags|=4096 if record[12][/m/]
  1192.        flags|=8192 if record[12][/n/]
  1193.        flags|=16384 if record[12][/o/]
  1194.        flags|=32768 if record[12][/p/]
  1195.      rescue
  1196.        oldmessage=$!.message
  1197.        raise if !haveRsAttacks
  1198.        begin
  1199.          oldrecord=pbGetCsvRecord(thisline,lineno,[0,"unss",nil,nil,nil,nil])
  1200.        rescue
  1201.          raise $!.message+"\r\n"+oldmessage
  1202.        end
  1203.        oldmovedata=PBMoveDataOld.new(oldrecord[0])
  1204.        flags=oldmovedata.flags
  1205.        record=[oldrecord[0],oldrecord[1],oldrecord[2],
  1206.           oldmovedata.function,
  1207.           oldmovedata.basedamage,
  1208.           oldmovedata.type,
  1209.           oldmovedata.category,
  1210.           oldmovedata.accuracy,
  1211.           oldmovedata.totalpp,
  1212.           oldmovedata.addlEffect,
  1213.           oldmovedata.target,
  1214.           oldmovedata.priority,
  1215.           oldmovedata.flags,
  1216.           0, # No contest type defined
  1217.           oldrecord[3]]
  1218.      end
  1219.      pbCheckWord(record[3],_INTL("Function code"))
  1220.      pbCheckByte(record[4],_INTL("Base damage"))
  1221.      if record[6]==2 && record[4]!=0
  1222.        raise _INTL("Status moves must have a base damage of 0, use either Physical or Special\r\n{1}",FileLineData.linereport)
  1223.      end
  1224.      if record[6]!=2 && record[4]==0
  1225.        print _INTL(
  1226.           "Warning: Physical and special moves can't have a base damage of 0, changing to a Status move\r\n{1}",FileLineData.linereport)
  1227.        record[6]=2
  1228.      end
  1229.      pbCheckByte(record[7],_INTL("Accuracy"))
  1230.      pbCheckByte(record[8],_INTL("Total PP"))
  1231.      pbCheckByte(record[9],_INTL("Additional Effect"))
  1232.      pbCheckWord(record[10],_INTL("Target"))
  1233.      pbCheckSignedByte(record[11],_INTL("Priority"))
  1234.      maxValue=[maxValue,record[0]].max
  1235.      movedata[record[0]]=[
  1236.         record[3],  # Function code
  1237.         record[4],  # Damage
  1238.         record[5],  # Type
  1239.         record[6],  # Category
  1240.         record[7],  # Accuracy
  1241.         record[8],  # Total PP
  1242.         record[9],  # Effect chance
  1243.         record[10], # Target
  1244.         record[11], # Priority
  1245.         flags,      # Flags
  1246.         record[13]  # Contest type
  1247.      ].pack("vCCCCCCvCvC")
  1248.      movenames[record[0]]=record[2]  # Name
  1249.      movedescs[record[0]]=record[14] # Description
  1250.      records.push(record)
  1251.   }
  1252.   defaultdata=[0,0,0,0,0,0,0,0,0,0,0].pack("vCCCCCCvCvC")
  1253.   File.open("Data/moves.dat","wb"){|file|
  1254.      for i in 0...movedata.length
  1255.        file.write(movedata[i] ? movedata[i] : defaultdata)
  1256.      end
  1257.   }
  1258.   MessageTypes.setMessages(MessageTypes::Moves,movenames)
  1259.   MessageTypes.setMessages(MessageTypes::MoveDescriptions,movedescs)
  1260.   code="class PBMoves\r\n"
  1261.   for rec in records
  1262.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1263.   end
  1264.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::Moves,id)\r\nend"
  1265.   code+="\r\ndef self.getCount\r\nreturn #{records.length}\r\nend"
  1266.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1267.   eval(code)
  1268.   pbAddScript(code,"PBMoves")
  1269. end
  1270.  
  1271. def pbCompileContestMoves
  1272.   records=[]
  1273.   contestmovenames=[]
  1274.   contestmovedescs=[]
  1275.   contestmovedata=[]
  1276.   maxValue=0
  1277.   haveRsAttacks=pbRgssExists?("Data/rsattacks.dat")
  1278.   pbCompilerEachPreppedLine("PBS/contestmoves.txt"){|line,lineno|
  1279.      thisline=line.clone
  1280.      record=[]
  1281.      flags=0
  1282.  
  1283.        record=pbGetCsvRecord(line,lineno,[0,"vnseUUUs",
  1284.           nil,nil,nil,["Cool","Beauty","Cute","Smart","Tough"],nil,nil,nil,nil
  1285.        ])
  1286.      
  1287.      maxValue=[maxValue,record[0]].max
  1288.      contestmovedata[record[0]]=[
  1289.         record[3],  # Contest Type
  1290.         record[4],  # Hearts
  1291.         record[5],  # Jam
  1292.         record[6]   # Function Code
  1293.      ].pack("CCCC")
  1294.      contestmovenames[record[0]]=record[2]  # Name
  1295.      contestmovedescs[record[0]]=record[7] # Description
  1296.      records.push(record)
  1297.      }
  1298.   defaultdata=[0,0,0,0].pack("CCCC")
  1299.   File.open("Data/contestmoves.dat","wb"){|file|
  1300.      for i in 0...contestmovedata.length
  1301.        file.write(contestmovedata[i] ? contestmovedata[i] : defaultdata)
  1302.      end
  1303.   }
  1304.   MessageTypes.setMessages(MessageTypes::ContestMoves,contestmovenames)
  1305.   MessageTypes.setMessages(MessageTypes::ContestMoveDescriptions,contestmovedescs)
  1306.   code="class PBContestMoves\r\n"
  1307.   for rec in records
  1308.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1309.   end
  1310.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::Moves,id)\r\nend"
  1311.   code+="\r\ndef self.getCount\r\nreturn #{records.length}\r\nend"
  1312.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1313.   eval(code)
  1314.   pbAddScript(code,"PBContestMoves")
  1315. end
  1316.  
  1317. def pbCompileAbilities
  1318.   records=[]
  1319.   movenames=[]
  1320.   movedescs=[]
  1321.   maxValue=0
  1322.   pbCompilerEachPreppedLine("PBS/abilities.txt"){|line,lineno|
  1323.      record=pbGetCsvRecord(line,lineno,[0,"vnss"])
  1324.      movenames[record[0]]=record[2]
  1325.      movedescs[record[0]]=record[3]
  1326.      maxValue=[maxValue,record[0]].max
  1327.      records.push(record)
  1328.   }
  1329.   MessageTypes.setMessages(MessageTypes::Abilities,movenames)
  1330.   MessageTypes.setMessages(MessageTypes::AbilityDescs,movedescs)
  1331.   code="class PBAbilities\r\n"
  1332.   for rec in records
  1333.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1334.   end
  1335.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::Abilities,id)\r\nend"
  1336.   code+="\r\ndef self.getCount\r\nreturn #{records.length}\r\nend\r\n"
  1337.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1338.   eval(code)
  1339.   pbAddScript(code,"PBAbilities")
  1340. end  
  1341.  
  1342. def pbExtractTrainers
  1343.   trainertypes=nil
  1344.   pbRgssOpen("Data/trainertypes.dat","rb"){|f|
  1345.      trainertypes=Marshal.load(f)
  1346.   }
  1347.   return if !trainertypes
  1348.   File.open("trainertypes.txt","wb"){|f|
  1349.      f.write(0xEF.chr)
  1350.      f.write(0xBB.chr)
  1351.      f.write(0xBF.chr)
  1352.      for i in 0...trainertypes.length
  1353.        next if !trainertypes[i]
  1354.        record=trainertypes[i]
  1355.        begin
  1356.          cnst=getConstantName(PBTrainers,record[0])
  1357.        rescue
  1358.          next
  1359.        end
  1360.        f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s\r\n",
  1361.           record[0],csvquote(cnst),csvquote(record[2]),
  1362.           record[3],csvquote(record[4]),csvquote(record[5]),csvquote(record[6]),
  1363.           record[7] ? ["Male","Female","Mixed"][record[7]] : "Mixed"
  1364.        ))
  1365.      end
  1366.   }
  1367. end
  1368.  
  1369. def pbCompileTrainers
  1370.   # Trainer types
  1371.   records=[]
  1372.   trainernames=[]
  1373.   count=0
  1374.   maxValue=0
  1375.   pbCompilerEachPreppedLine("PBS/trainertypes.txt"){|line,lineno|
  1376.      record=pbGetCsvRecord(line,lineno,[0,"unsUSSSeU", # ID can be 0
  1377.         nil,nil,nil,nil,nil,nil,nil,{
  1378.         ""=>2,"Male"=>0,"M"=>0,"0"=>0,"Female"=>1,"F"=>1,"1"=>1,"Mixed"=>2,"X"=>2,"2"=>2
  1379.         },nil]
  1380.      )
  1381.      if record[3] && (record[3]<0 || record[3]>255)
  1382.        raise _INTL("Bad money amount (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
  1383.      end
  1384.      record[3]=30 if !record[3]
  1385.      if record[8] && (record[8]<0 || record[8]>255)
  1386.        raise _INTL("Bad skill value (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
  1387.      end
  1388.      record[8]=record[3] if !record[8]
  1389.      trainernames[record[0]]=record[2]
  1390.      if records[record[0]]
  1391.        raise _INTL("Two trainer types ({1} and {2}) have the same ID ({3}), which is not allowed.\r\n{4}",
  1392.           records[record[0]][1],record[1],record[0],FileLineData.linereport)
  1393.      end
  1394.      records[record[0]]=record
  1395.      maxValue=[maxValue,record[0]].max
  1396.   }
  1397.   count=records.compact.length
  1398.   MessageTypes.setMessages(MessageTypes::TrainerTypes,trainernames)
  1399.   code="class PBTrainers\r\n"
  1400.   for rec in records
  1401.     next if !rec
  1402.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1403.   end
  1404.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::TrainerTypes,id)\r\nend"
  1405.   code+="\r\ndef self.getCount\r\nreturn #{count}\r\nend"
  1406.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1407.   eval(code)
  1408.   pbAddScript(code,"PBTrainers")
  1409.   File.open("Data/trainertypes.dat","wb"){|f|
  1410.      Marshal.dump(records,f)
  1411.   }
  1412.   # Individual trainers
  1413.   lines=[]
  1414.   linenos=[]
  1415.   lineno=1
  1416.   File.open("PBS/trainers.txt","rb"){|f|
  1417.      FileLineData.file="PBS/trainers.txt"
  1418.      f.each_line {|line|
  1419.         line=prepline(line)
  1420.         if line!=""
  1421.           lines.push(line)
  1422.           linenos.push(lineno)
  1423.         end
  1424.         lineno+=1
  1425.      }
  1426.   }
  1427.   nameoffset=0
  1428.   trainers=[]
  1429.   trainernames.clear
  1430.   i=0; loop do break unless i<lines.length
  1431.     FileLineData.setLine(lines[i],linenos[i])
  1432.     trainername=parseTrainer(lines[i])
  1433.     FileLineData.setLine(lines[i+1],linenos[i+1])
  1434.     nameline=strsplit(lines[i+1],/\s*,\s*/)
  1435.     name=nameline[0]
  1436.     raise _INTL("Trainer name too long\r\n{1}",FileLineData.linereport) if name.length>=0x10000
  1437.     trainernames.push(name)
  1438.     partyid=0
  1439.     if nameline[1] && nameline[1]!=""
  1440.       raise _INTL("Expected a number for the trainer battle ID\r\n{1}",FileLineData.linereport) if !nameline[1][/^\d+$/]
  1441.       partyid=nameline[1].to_i
  1442.     end
  1443.     FileLineData.setLine(lines[i+2],linenos[i+2])
  1444.     items=strsplit(lines[i+2],/\s*,\s*/)
  1445.     items[0].gsub!(/^\s+/,"")   # Number of Pokémon
  1446.     raise _INTL("Expected a number for the number of Pokémon\r\n{1}",FileLineData.linereport) if !items[0][/^\d+$/]
  1447.     numpoke=items[0].to_i
  1448.     realitems=[]
  1449.     for j in 1...items.length   # Items held by Trainer
  1450.       realitems.push(parseItem(items[j])) if items[j] && items[j]!=""
  1451.     end
  1452.     pkmn=[]
  1453.     for j in 0...numpoke
  1454.       FileLineData.setLine(lines[i+j+3],linenos[i+j+3])
  1455.       poke=strsplit(lines[i+j+3],/\s*,\s*/)
  1456.       begin
  1457.         poke[TPSPECIES]=parseSpecies(poke[TPSPECIES])   # Species
  1458.       rescue
  1459.         raise _INTL("Expected a species name: {1}\r\n{2}",poke[0],FileLineData.linereport)
  1460.       end
  1461.       poke[TPLEVEL]=poke[TPLEVEL].to_i   # Level
  1462.       raise _INTL("Bad level: {1} (must be from 1-{2})\r\n{3}",poke[TPLEVEL],
  1463.         PBExperience::MAXLEVEL,FileLineData.linereport) if poke[TPLEVEL]<=0 || poke[TPLEVEL]>PBExperience::MAXLEVEL
  1464.       if !poke[TPITEM] || poke[TPITEM]==""   # Held item
  1465.         poke[TPITEM]=TPDEFAULTS[TPITEM]
  1466.       else
  1467.         poke[TPITEM]=parseItem(poke[TPITEM])
  1468.       end
  1469.       moves=[]
  1470.       for j in [TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4]   # Moves
  1471.         moves.push(parseMove(poke[j])) if poke[j] && poke[j]!=""
  1472.       end
  1473.       for j in 0...4
  1474.         index=[TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4][j]
  1475.         if moves[j] && moves[j]!=0
  1476.           poke[index]=moves[j]
  1477.         else
  1478.           poke[index]=TPDEFAULTS[index]
  1479.         end
  1480.       end
  1481.       if !poke[TPABILITY] || poke[TPABILITY]==""   # Ability
  1482.         poke[TPABILITY]=TPDEFAULTS[TPABILITY]
  1483.       else
  1484.         poke[TPABILITY]=poke[TPABILITY].to_i
  1485.         raise _INTL("Bad abilityflag: {1} (must be 0 or 1 or 2-5)\r\n{2}",poke[TPABILITY],FileLineData.linereport) if poke[TPABILITY]<0 || poke[TPABILITY]>5
  1486.       end
  1487.       if !poke[TPGENDER] || poke[TPGENDER]==""   # Gender
  1488.         poke[TPGENDER]=TPDEFAULTS[TPGENDER]
  1489.       else
  1490.         poke[TPGENDER]=poke[TPGENDER].to_i
  1491.         raise _INTL("Bad genderflag: {1} (must be 0 or 1)\r\n{2}",poke[TPGENDER],FileLineData.linereport) if poke[TPGENDER]<0 || poke[TPGENDER]>1
  1492.       end
  1493.       if !poke[TPFORM] || poke[TPFORM]==""   # Form
  1494.         poke[TPFORM]=TPDEFAULTS[TPFORM]
  1495.       else
  1496.         poke[TPFORM]=poke[TPFORM].to_i
  1497.         raise _INTL("Bad form: {1} (must be 0 or greater)\r\n{2}",poke[TPFORM],FileLineData.linereport) if poke[TPFORM]<0
  1498.       end
  1499.       poke[TPSHINY]=(!poke[TPSHINY] || poke[TPSHINY]=="") ? TPDEFAULTS[TPSHINY] : csvBoolean!(poke[TPSHINY].clone)   # Shiny
  1500.       poke[TPNATURE]=(!poke[TPNATURE] || poke[TPNATURE]=="") ? TPDEFAULTS[TPNATURE] : parseNature(poke[TPNATURE])   # Nature
  1501.       if !poke[TPIV] || poke[TPIV]==""   # IVs
  1502.         poke[TPIV]=TPDEFAULTS[TPIV]
  1503.       else
  1504.         poke[TPIV]=poke[TPIV].to_i
  1505.         raise _INTL("Bad IV: {1} (must be from 0-31)\r\n{2}",poke[TPIV],FileLineData.linereport) if poke[TPIV]<0 || poke[TPIV]>31
  1506.       end
  1507.       if !poke[TPHAPPINESS] || poke[TPHAPPINESS]==""   # Happiness
  1508.         poke[TPHAPPINESS]=TPDEFAULTS[TPHAPPINESS]
  1509.       else
  1510.         poke[TPHAPPINESS]=poke[TPHAPPINESS].to_i
  1511.         raise _INTL("Bad happiness: {1} (must be from 0-255)\r\n{2}",poke[TPHAPPINESS],FileLineData.linereport) if poke[TPHAPPINESS]<0 || poke[TPHAPPINESS]>255
  1512.       end
  1513.       if !poke[TPNAME] || poke[TPNAME]==""   # Nickname
  1514.         poke[TPNAME]=TPDEFAULTS[TPNAME]
  1515.       else
  1516.         poke[TPNAME]=poke[TPNAME].to_s
  1517.         raise _INTL("Bad nickname: {1} (must be 1-10 characters)\r\n{2}",poke[TPNAME],FileLineData.linereport) if (poke[TPNAME].to_s).length>10
  1518.       end
  1519.       poke[TPSHADOW]=(!poke[TPSHADOW] || poke[TPSHADOW]=="") ? TPDEFAULTS[TPSHADOW] : csvBoolean!(poke[TPSHADOW].clone)   # Shadow
  1520.       if !poke[TPBALL] || poke[TPBALL]==""   # Ball
  1521.         poke[TPBALL]=TPDEFAULTS[TPBALL]
  1522.       else
  1523.         poke[TPBALL]=poke[TPBALL].to_i
  1524.         raise _INTL("Bad form: {1} (must be 0 or greater)\r\n{2}",poke[TPBALL],FileLineData.linereport) if poke[TPBALL]<0
  1525.       end
  1526.       pkmn.push(poke)
  1527.     end
  1528.     i+=3+numpoke
  1529.     MessageTypes.setMessagesAsHash(MessageTypes::TrainerNames,trainernames)
  1530.     trainers.push([trainername,name,realitems,pkmn,partyid])
  1531.     nameoffset+=name.length
  1532.   end
  1533.   save_data(trainers,"Data/trainers.dat")
  1534. end
  1535.  
  1536. def removeConstantValue(mod,value)
  1537.   for c in mod.constants
  1538.     if mod.const_get(c.to_sym)==value
  1539.       mod.send(:remove_const,c.to_sym)
  1540.     end
  1541.   end
  1542. end
  1543.  
  1544. def setConstantName(mod,value,name)
  1545.   for c in mod.constants
  1546.     if mod.const_get(c.to_sym)==value
  1547.       mod.send(:remove_const,c.to_sym)
  1548.     end
  1549.   end
  1550.   mod.const_set(name,value)
  1551. end
  1552.  
  1553. def getConstantName(mod,value)
  1554.   for c in mod.constants
  1555.     return c if mod.const_get(c.to_sym)==value
  1556.   end
  1557.   raise _INTL("Value {1} not defined by a constant in {2}",value,mod.name)
  1558. end
  1559.  
  1560. def pbTMRS
  1561.   rstm=[:FOCUSPUNCH,:DRAGONCLAW,
  1562.      :WATERPULSE,:CALMMIND,:ROAR,:TOXIC,
  1563.      :HAIL,:BULKUP,:BULLETSEED,:HIDDENPOWER,
  1564.      :SUNNYDAY,:TAUNT,:ICEBEAM,:BLIZZARD,
  1565.      :HYPERBEAM,:LIGHTSCREEN,:PROTECT,
  1566.      :RAINDANCE,:GIGADRAIN,:SAFEGUARD,
  1567.      :FRUSTRATION,:SOLARBEAM,:IRONTAIL,
  1568.      :THUNDERBOLT,:THUNDER,:EARTHQUAKE,
  1569.      :RETURN,:DIG,:PSYCHIC,:SHADOWBALL,
  1570.      :BRICKBREAK,:DOUBLETEAM,:REFLECT,
  1571.      :SHOCKWAVE,:FLAMETHROWER,:SLUDGEBOMB,
  1572.      :SANDSTORM,:FIREBLAST,:ROCKTOMB,
  1573.      :AERIALACE,:TORMENT,:FACADE,:SECRETPOWER,
  1574.      :REST,:ATTRACT,:THIEF,:STEELWING,:SKILLSWAP,
  1575.      :SNATCH,:OVERHEAT,:CUT,:FLY,:SURF,:STRENGTH,
  1576.      :FLASH,:ROCKSMASH,:WATERFALL,:DIVE]
  1577.   ret=[]
  1578.   for i in 0...rstm.length
  1579.     ret.push((parseMove(rstm.to_s) rescue 0))
  1580.   end
  1581.   return ret
  1582. end
  1583.  
  1584. def pbCompileMachines
  1585.   lineno=1
  1586.   havesection=false
  1587.   sectionname=nil
  1588.   sections=[]
  1589.   if safeExists?("PBS/tm.txt")
  1590.     f=File.open("PBS/tm.txt","rb")
  1591.     FileLineData.file="PBS/tm.txt"
  1592.     f.each_line {|line|
  1593.        if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  1594.          line=line[3,line.length-3]
  1595.        end
  1596.        FileLineData.setLine(line,lineno)
  1597.        if !line[/^\#/] && !line[/^\s*$/]
  1598.          if line[/^\s*\[\s*(.*)\s*\]\s*$/]
  1599.            sectionname=parseMove($~[1])
  1600.            sections[sectionname]=WordArray.new
  1601.            havesection=true
  1602.          else
  1603.            if sectionname==nil
  1604.              raise _INTL("Expected a section at the beginning of the file.  This error may also occur if the file was not saved in UTF-8.\r\n{1}",FileLineData.linereport)
  1605.            end
  1606.            specieslist=line.sub(/\s+$/,"").split(",")
  1607.            for species in specieslist
  1608.              next if !species || species==""
  1609.              sec=sections[sectionname]
  1610.              sec[sec.length]=parseSpecies(species)
  1611.            end
  1612.          end
  1613.        end
  1614.        lineno+=1
  1615.        if lineno%500==0
  1616.          Graphics.update
  1617.        end
  1618.        if lineno%50==0
  1619.          Win32API.SetWindowText(_INTL("Processing line {1}",lineno))
  1620.        end
  1621.     }
  1622.     f.close
  1623.   elsif safeExists?("Data/tmRS.dat")
  1624.     tmrs=pbTMRS()
  1625.     for i in 0...58
  1626.       next if !tmrs[i] || tmrs[i]==0
  1627.       sections[tmrs[i]]=[]
  1628.     end
  1629.     File.open("Data/tmRS.dat","rb"){|f|
  1630.        species=1
  1631.        while !f.eof?
  1632.          data=f.read(8)+"\0\0\0\0\0\0\0\0"
  1633.          for i in 0...58
  1634.            next if !tmrs[i] || tmrs[i]==0
  1635.            if (data[i>>3]&(1<<(i&7)))!=0
  1636.              sections[tmrs[i]].push(species)
  1637.            end
  1638.          end
  1639.          species+=1
  1640.        end
  1641.     }
  1642.   end
  1643.   save_data(sections,"Data/tm.dat")
  1644. end
  1645.  
  1646. def checkEnumField(ret,enumer)
  1647.   if enumer.is_a?(Module)
  1648.     begin
  1649.       if ret=="" || !enumer.const_defined?(ret)
  1650.         raise _INTL("Undefined value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
  1651.       end
  1652.       rescue NameError
  1653.       raise _INTL("Incorrect value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
  1654.     end
  1655.     return enumer.const_get(ret.to_sym)
  1656.   elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
  1657.     enumer=Object.const_get(enumer.to_sym)
  1658.     begin
  1659.       if ret=="" || !enumer.const_defined?(ret)
  1660.         raise _INTL("Undefined value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
  1661.       end
  1662.       rescue NameError
  1663.       raise _INTL("Incorrect value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
  1664.     end
  1665.     return enumer.const_get(ret.to_sym)
  1666.   elsif enumer.is_a?(Array)
  1667.     idx=findIndex(enumer){|item| ret==item}
  1668.     if idx<0
  1669.       raise _INTL("Undefined value {1} (expected one of: {2})\r\n{3}",ret,enumer.inspect,FileLineData.linereport)
  1670.     end
  1671.     return idx
  1672.   elsif enumer.is_a?(Hash)
  1673.     value=enumer[ret]
  1674.     if value==nil
  1675.       raise _INTL("Undefined value {1} (expected one of: {2})\r\n{3}",ret,enumer.keys.inspect,FileLineData.linereport)
  1676.     end
  1677.     return value
  1678.   end
  1679.   raise _INTL("Enumeration not defined\r\n{1}",FileLineData.linereport)
  1680. end
  1681.  
  1682. def csvEnumField!(value,enumer,key,section)
  1683.   ret=csvfield!(value)
  1684.   return checkEnumField(ret,enumer)
  1685. end
  1686.  
  1687. def csvEnumFieldOrInt!(value,enumer,key,section)
  1688.   ret=csvfield!(value)
  1689.   if ret[/\-?\d+/]
  1690.     return ret.to_i
  1691.   end
  1692.   return checkEnumField(ret,enumer)
  1693. end
  1694.  
  1695. def pbEachFileSectionEx(f)
  1696.   lineno=1
  1697.   havesection=false
  1698.   sectionname=nil
  1699.   lastsection={}
  1700.   f.each_line {|line|
  1701.      if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  1702.        line=line[3,line.length-3]
  1703.      end
  1704.      if !line[/^\#/] && !line[/^\s*$/]
  1705.        if line[/^\s*\[\s*(.*)\s*\]\s*$/]
  1706.          if havesection
  1707.            yield lastsection,sectionname
  1708.          end
  1709.          sectionname=$~[1]
  1710.          havesection=true
  1711.          lastsection={}
  1712.        else
  1713.         if sectionname==nil
  1714.           raise _INTL("Expected a section at the beginning of the file.  This error may also occur if the file was not saved in UTF-8.\r\n{1}",FileLineData.linereport)
  1715.         end
  1716.         if !line[/^\s*(\w+)\s*=\s*(.*)$/]
  1717.           raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
  1718.         end
  1719.         r1=$~[1]
  1720.         r2=$~[2]
  1721.         lastsection[r1]=r2.gsub(/\s+$/,"")
  1722.       end
  1723.     end
  1724.     lineno+=1
  1725.     if lineno%500==0
  1726.       Graphics.update
  1727.     end
  1728.     if lineno%50==0
  1729.       Win32API.SetWindowText(_INTL("Processing line {1}",lineno))
  1730.     end
  1731.   }
  1732.   if havesection
  1733.     yield lastsection,sectionname
  1734.   end
  1735. end
  1736.  
  1737. def pbEachFileSection(f)
  1738.   pbEachFileSectionEx(f) {|section,name|
  1739.      if block_given? && name[/^\d+$/]
  1740.        yield section,name.to_i
  1741.      end
  1742.   }
  1743. end
  1744.  
  1745.  
  1746.  
  1747. class SignedWordArray
  1748.   include Enumerable
  1749.  
  1750.   def initialize(data=nil)
  1751.     if data
  1752.       @a=data.unpack("v*")
  1753.     else
  1754.       @a=[]
  1755.     end
  1756.   end
  1757.  
  1758.   def []=(i,value)
  1759.     @a[i]=value
  1760.   end
  1761.  
  1762.   def [](i)
  1763.     v=@a[i]
  1764.     return v<0x8000 ? v : -((~v)&0xFFFF)-1
  1765.   end
  1766.  
  1767.   def length;@a.length;end
  1768.   def size;@a.size;end
  1769.  
  1770.   def fillNils(length,value)
  1771.     for i in 0...length
  1772.       @a[i]=value if !@a[i]
  1773.     end
  1774.   end
  1775.  
  1776.   def each
  1777.     @a.each {|i| yield i}
  1778.   end
  1779.  
  1780.   def self._load(str)
  1781.     return self.new(str)
  1782.   end
  1783.  
  1784.   def _dump(depth=100)
  1785.     return @a.pack("v*")
  1786.   end
  1787. end
  1788.  
  1789.  
  1790.  
  1791. class ByteArray
  1792.   include Enumerable
  1793.  
  1794.   def initialize(data=nil)
  1795.     if data
  1796.       @a=data.unpack("C*")
  1797.     else
  1798.       @a=[]
  1799.     end
  1800.   end
  1801.  
  1802.   def []=(i,value)
  1803.     @a[i]=value
  1804.   end
  1805.  
  1806.   def [](i)
  1807.     return @a[i]
  1808.   end
  1809.  
  1810.   def length;@a.length;end
  1811.   def size;@a.size;end
  1812.  
  1813.   def fillNils(length,value)
  1814.     for i in 0...length
  1815.       @a[i]=value if !@a[i]
  1816.     end
  1817.   end
  1818.  
  1819.   def each
  1820.     @a.each {|i| yield i}
  1821.   end
  1822.  
  1823.   def self._load(str)
  1824.     return self.new(str)
  1825.   end
  1826.  
  1827.   def _dump(depth=100)
  1828.     return @a.pack("C*")
  1829.   end
  1830. end
  1831.  
  1832.  
  1833.  
  1834. class WordArray
  1835.   include Enumerable
  1836.  
  1837.   def initialize(data=nil)
  1838.     if data
  1839.       @a=data.unpack("v*")
  1840.     else
  1841.       @a=[]
  1842.     end
  1843.   end
  1844.  
  1845.   def []=(i,value)
  1846.     @a[i]=value
  1847.   end
  1848.  
  1849.   def [](i)
  1850.     return @a[i]
  1851.   end
  1852.  
  1853.   def length;@a.length;end
  1854.   def size;@a.size;end
  1855.  
  1856.   def fillNils(length,value)
  1857.     for i in 0...length
  1858.       @a[i]=value if !@a[i]
  1859.     end
  1860.   end
  1861.  
  1862.   def each
  1863.     @a.each {|i| yield i}
  1864.   end
  1865.  
  1866.   def self._load(str)
  1867.     return self.new(str)
  1868.   end
  1869.  
  1870.   def _dump(depth=100)
  1871.     return @a.pack("v*")
  1872.   end
  1873. end
  1874.  
  1875.  
  1876.  
  1877. def pbEachSection(f)
  1878.   lineno=1
  1879.   havesection=false
  1880.   sectionname=nil
  1881.   lastsection=[]
  1882.   f.each_line {|line|
  1883.      if lineno==1&&line[0]==0xEF&&line[1]==0xBB&&line[2]==0xBF
  1884.        line=line[3,line.length-3]
  1885.      end
  1886.      if !line[/^\#/] && !line[/^\s*$/]
  1887.        if line[/^\s*\[\s*(.+?)\s*\]\s*$/]
  1888.          if havesection
  1889.            yield lastsection,sectionname
  1890.          end
  1891.          sectionname=$~[1]
  1892.          lastsection=[]
  1893.          havesection=true
  1894.        else
  1895.          if sectionname==nil
  1896.            raise _INTL("Expected a section at the beginning of the file (line {1}). Sections begin with '[name of section]'",lineno)
  1897.          end
  1898.          lastsection.push(line.gsub(/^\s+/,"").gsub(/\s+$/,""))
  1899.        end
  1900.      end
  1901.      lineno+=1
  1902.      if lineno%500==0
  1903.        Graphics.update
  1904.      end
  1905.   }
  1906.   if havesection
  1907.     yield lastsection,sectionname
  1908.   end
  1909. end
  1910.  
  1911. def pbCompileTrainerLists
  1912.   btTrainersRequiredTypes={
  1913.      "Trainers"=>[0,"s"],
  1914.      "Pokemon"=>[1,"s"],
  1915.      "Challenges"=>[2,"*s"]
  1916.   }
  1917.   if !safeExists?("PBS/trainerlists.txt")
  1918.     File.open("PBS/trainerlists.txt","wb"){|f|
  1919.        f.write("[DefaultTrainerList]\r\nTrainers=bttrainers.txt\r\nPokemon=btpokemon.txt\r\n")
  1920.     }
  1921.   end
  1922.   database=[]
  1923.   sections=[]
  1924.   MessageTypes.setMessagesAsHash(MessageTypes::BeginSpeech,[])
  1925.   MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechWin,[])
  1926.   MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechLose,[])
  1927.   File.open("PBS/trainerlists.txt","rb"){|f|
  1928.      pbEachFileSectionEx(f){|section,name|
  1929.         next if name!="DefaultTrainerList" && name!="TrainerList"
  1930.         rsection=[]
  1931.         for key in section.keys
  1932.           FileLineData.setSection(name,key,section[key])
  1933.           schema=btTrainersRequiredTypes[key]
  1934.           next if key=="Challenges" && name=="DefaultTrainerList"
  1935.           next if !schema
  1936.           record=pbGetCsvRecord(section[key],0,schema)
  1937.           rsection[schema[0]]=record  
  1938.         end
  1939.         if !rsection[0]
  1940.           raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
  1941.         end
  1942.         if !rsection[1]
  1943.           raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
  1944.         end
  1945.         rsection[3]=rsection[0]
  1946.         rsection[4]=rsection[1]
  1947.         rsection[5]=(name=="DefaultTrainerList")
  1948.         if safeExists?("PBS/"+rsection[0])
  1949.           rsection[0]=pbCompileBTTrainers("PBS/"+rsection[0])
  1950.         else
  1951.           rsection[0]=[]
  1952.         end
  1953.         if safeExists?("PBS/"+rsection[1])
  1954.           filename="PBS/"+rsection[1]
  1955.           rsection[1]=[]
  1956.           pbCompilerEachCommentedLine(filename){|line,lineno|
  1957.              rsection[1].push(PBPokemon.fromInspected(line))
  1958.           }
  1959.         else
  1960.           rsection[1]=[]
  1961.         end
  1962.         if !rsection[2]
  1963.           rsection[2]=[]
  1964.         end
  1965.         while rsection[2].include?("")
  1966.           rsection[2].delete("")
  1967.         end
  1968.         rsection[2].compact!
  1969.         sections.push(rsection)
  1970.      }
  1971.   }
  1972.   save_data(sections,"Data/trainerlists.dat")
  1973. end
  1974.  
  1975.  
  1976. def pbCompilePhoneData
  1977.   return if !safeExists?("PBS/phone.txt")
  1978.   database=PhoneDatabase.new
  1979.   sections=[]
  1980.   File.open("PBS/phone.txt","rb"){|f|
  1981.      pbEachSection(f){|section,name|
  1982.         if name=="<Generics>"
  1983.           database.generics=section
  1984.           sections.concat(section)
  1985.         elsif name=="<BattleRequests>"
  1986.           database.battleRequests=section
  1987.           sections.concat(section)
  1988.         elsif name=="<GreetingsMorning>"
  1989.           database.greetingsMorning=section
  1990.           sections.concat(section)
  1991.         elsif name=="<GreetingsEvening>"
  1992.           database.greetingsEvening=section
  1993.           sections.concat(section)
  1994.         elsif name=="<Greetings>"
  1995.           database.greetings=section
  1996.           sections.concat(section)
  1997.         elsif name=="<Bodies1>"
  1998.           database.bodies1=section
  1999.           sections.concat(section)
  2000.         elsif name=="<Bodies2>"
  2001.           database.bodies2=section
  2002.           sections.concat(section)
  2003.         end
  2004.      }
  2005.   }
  2006.   MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages,sections)
  2007.   save_data(database,"Data/phone.dat")
  2008. end
  2009.  
  2010. def frozenArrayValue(arr)
  2011.   typestring=""
  2012.   for i in 0...arr.length
  2013.     if i>0
  2014.       typestring+=((i%20)==0) ? ",\r\n" : ","
  2015.     end
  2016.     typestring+=arr[i].to_s
  2017.   end
  2018.   return "["+typestring+"].freeze"
  2019. end
  2020.  
  2021. def pbWriteDefaultTypes
  2022.   if !safeExists?("PBS/types.txt")
  2023.     File.open("PBS/types.txt","w"){|f|
  2024. fx=<<END
  2025. [0]
  2026. Name=Normal
  2027. InternalName=NORMAL
  2028. Weaknesses=FIGHTING
  2029. Immunities=GHOST
  2030.  
  2031. [1]
  2032. Name=Fighting
  2033. InternalName=FIGHTING
  2034. Weaknesses=FLYING,PSYCHIC
  2035. Resistances=ROCK,BUG,DARK
  2036.  
  2037. [2]
  2038. Name=Flying
  2039. InternalName=FLYING
  2040. Weaknesses=ROCK,ELECTRIC,ICE
  2041. Resistances=FIGHTING,BUG,GRASS
  2042. Immunities=GROUND
  2043.  
  2044. [3]
  2045. Name=Poison
  2046. InternalName=POISON
  2047. Weaknesses=GROUND,PSYCHIC
  2048. Resistances=FIGHTING,POISON,BUG,GRASS
  2049.  
  2050. [4]
  2051. Name=Ground
  2052. InternalName=GROUND
  2053. Weaknesses=WATER,GRASS,ICE
  2054. Resistances=POISON,ROCK
  2055. Immunities=ELECTRIC
  2056.  
  2057. [5]
  2058. Name=Rock
  2059. InternalName=ROCK
  2060. Weaknesses=FIGHTING,GROUND,STEEL,WATER,GRASS
  2061. Resistances=NORMAL,FLYING,POISON,FIRE
  2062.  
  2063. [6]
  2064. Name=Bug
  2065. InternalName=BUG
  2066. Weaknesses=FLYING,ROCK,FIRE
  2067. Resistances=FIGHTING,GROUND,GRASS
  2068.  
  2069. [7]
  2070. Name=Ghost
  2071. InternalName=GHOST
  2072. Weaknesses=GHOST,DARK
  2073. Resistances=POISON,BUG
  2074. Immunities=NORMAL,FIGHTING
  2075.  
  2076. [8]
  2077. Name=Steel
  2078. InternalName=STEEL
  2079. Weaknesses=FIGHTING,GROUND,FIRE
  2080. Resistances=NORMAL,FLYING,ROCK,BUG,GHOST,STEEL,GRASS,PSYCHIC,ICE,DRAGON,DARK
  2081. Immunities=POISON
  2082.  
  2083. [9]
  2084. Name=???
  2085. InternalName=QMARKS
  2086. IsPseudoType=true
  2087.  
  2088. [10]
  2089. Name=Fire
  2090. InternalName=FIRE
  2091. IsSpecialType=true
  2092. Weaknesses=GROUND,ROCK,WATER
  2093. Resistances=BUG,STEEL,FIRE,GRASS,ICE
  2094.  
  2095. [11]
  2096. Name=Water
  2097. InternalName=WATER
  2098. IsSpecialType=true
  2099. Weaknesses=GRASS,ELECTRIC
  2100. Resistances=STEEL,FIRE,WATER,ICE
  2101.  
  2102. [12]
  2103. Name=Grass
  2104. InternalName=GRASS
  2105. IsSpecialType=true
  2106. Weaknesses=FLYING,POISON,BUG,FIRE,ICE
  2107. Resistances=GROUND,WATER,GRASS,ELECTRIC
  2108.  
  2109. [13]
  2110. Name=Electric
  2111. InternalName=ELECTRIC
  2112. IsSpecialType=true
  2113. Weaknesses=GROUND
  2114. Resistances=FLYING,STEEL,ELECTRIC
  2115.  
  2116. [14]
  2117. Name=Psychic
  2118. InternalName=PSYCHIC
  2119. IsSpecialType=true
  2120. Weaknesses=BUG,GHOST,DARK
  2121. Resistances=FIGHTING,PSYCHIC
  2122.  
  2123. [15]
  2124. Name=Ice
  2125. InternalName=ICE
  2126. IsSpecialType=true
  2127. Weaknesses=FIGHTING,ROCK,STEEL,FIRE
  2128. Resistances=ICE
  2129.  
  2130. [16]
  2131. Name=Dragon
  2132. InternalName=DRAGON
  2133. IsSpecialType=true
  2134. Weaknesses=ICE,DRAGON
  2135. Resistances=FIRE,WATER,GRASS,ELECTRIC
  2136.  
  2137. [17]
  2138. Name=Dark
  2139. InternalName=DARK
  2140. IsSpecialType=true
  2141. Weaknesses=FIGHTING,BUG
  2142. Resistances=GHOST,DARK
  2143. Immunities=PSYCHIC
  2144.  
  2145. END
  2146. f.write(fx)
  2147.     }
  2148.   end
  2149. end
  2150.  
  2151. def pbCompileTypes
  2152.   pbWriteDefaultTypes
  2153.   sections=[]
  2154.   typechart=[]
  2155.   types=[]
  2156.   nameToType={}
  2157.   requiredtypes={
  2158.      "Name"=>[1,"s"],
  2159.      "InternalName"=>[2,"s"],
  2160.   }
  2161.   optionaltypes={
  2162.      "IsPseudoType"=>[3,"b"],
  2163.      "IsSpecialType"=>[4,"b"],
  2164.      "Weaknesses"=>[5,"*s"],
  2165.      "Resistances"=>[6,"*s"],
  2166.      "Immunities"=>[7,"*s"]
  2167.   }
  2168.   currentmap=-1
  2169.   foundtypes=[]
  2170.   pbCompilerEachCommentedLine("PBS/types.txt") {|line,lineno|
  2171.      if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
  2172.        sectionname=$~[1]
  2173.        if currentmap>=0
  2174.          for reqtype in requiredtypes.keys
  2175.            if !foundtypes.include?(reqtype)
  2176.              raise _INTL("Required value '{1}' not given in section '{2}'\r\n{3}",reqtype,currentmap,FileLineData.linereport)
  2177.            end
  2178.          end
  2179.          foundtypes.clear
  2180.        end
  2181.        currentmap=sectionname.to_i
  2182.        types[currentmap]=[currentmap,nil,nil,false,false,[],[],[]]
  2183.      else
  2184.        if currentmap<0
  2185.          raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
  2186.        end
  2187.        if !line[/^\s*(\w+)\s*=\s*(.*)$/]
  2188.          raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
  2189.        end
  2190.        matchData=$~
  2191.        schema=nil
  2192.        FileLineData.setSection(currentmap,matchData[1],matchData[2])
  2193.        if requiredtypes.keys.include?(matchData[1])
  2194.          schema=requiredtypes[matchData[1]]
  2195.          foundtypes.push(matchData[1])
  2196.        else
  2197.          schema=optionaltypes[matchData[1]]
  2198.        end
  2199.        if schema
  2200.          record=pbGetCsvRecord(matchData[2],lineno,schema)
  2201.          types[currentmap][schema[0]]=record
  2202.        end
  2203.      end
  2204.   }
  2205.   types.compact!
  2206.   maxValue=0
  2207.   for type in types; maxValue=[maxValue,type[0]].max; end
  2208.   pseudotypes=[]
  2209.   specialtypes=[]
  2210.   typenames=[]
  2211.   typeinames=[]
  2212.   typehash={}
  2213.   for type in types
  2214.     pseudotypes.push(type[0]) if type[3]
  2215.     typenames[type[0]]=type[1]
  2216.     typeinames[type[0]]=type[2]
  2217.     typehash[type[0]]=type
  2218.   end
  2219.   for type in types
  2220.     n=type[1]
  2221.     for w in type[5]; if !typeinames.include?(w)
  2222.       raise _INTL("'{0}' is not a defined type (PBS/types.txt, {1}, Weaknesses)",w,n)
  2223.     end; end
  2224.     for w in type[6]; if !typeinames.include?(w)
  2225.       raise _INTL("'{0}' is not a defined type (PBS/types.txt, {1}, Resistances)",w,n)
  2226.     end; end
  2227.     for w in type[7]; if !typeinames.include?(w)
  2228.       raise _INTL("'{0}' is not a defined type (PBS/types.txt, {1}, Immunities)",w,n)
  2229.     end; end
  2230.   end
  2231.   for i in 0..maxValue
  2232.     pseudotypes.push(i) if !typehash[i]
  2233.   end
  2234.   pseudotypes.sort!
  2235.   for type in types; specialtypes.push(type[0]) if type[4]; end
  2236.   specialtypes.sort!
  2237.   MessageTypes.setMessages(MessageTypes::Types,typenames)
  2238.   code="class PBTypes\r\n"
  2239.   for type in types
  2240.     code+="#{type[2]}=#{type[0]}\r\n"
  2241.   end
  2242.   code+="def PBTypes.getCount; return #{types.length}; end\r\n"
  2243.   code+="def PBTypes.maxValue; return #{maxValue}; end\r\n"
  2244.   code+="def PBTypes.getName(id)\r\nreturn pbGetMessage(MessageTypes::Types,id)\r\nend\r\n"
  2245.   count=maxValue+1
  2246.   for i in 0...count
  2247.     type=typehash[i]
  2248.     j=0; k=i; while j<count
  2249.       typechart[k]=2
  2250.       atype=typehash[j]
  2251.       if type && atype
  2252.         typechart[k]=4 if type[5].include?(atype[2]) # weakness
  2253.         typechart[k]=1 if type[6].include?(atype[2]) # resistance
  2254.         typechart[k]=0 if type[7].include?(atype[2]) # immune
  2255.       end
  2256.       j+=1
  2257.       k+=count
  2258.     end
  2259.   end
  2260.   code+="end\r\n"
  2261.   eval(code)
  2262.   save_data([pseudotypes,specialtypes,typechart],"Data/types.dat")
  2263.   pbAddScript(code,"PBTypes")
  2264.   Graphics.update
  2265. end
  2266.  
  2267. def pbCompilePokemonData
  2268.   sections=[]
  2269.   requiredtypes={
  2270.      "Name"=>[0,"s"],
  2271.      "Kind"=>[0,"s"],
  2272.      "InternalName"=>[0,"c"],
  2273.      "Pokedex"=>[0,"S"],
  2274.      "Moves"=>[0,"*uE",nil,PBMoves],
  2275.      "Color"=>[6,"e",["Red","Blue","Yellow","Green","Black","Brown","Purple","Gray","White","Pink"]],
  2276.      "Type1"=>[8,"e",PBTypes],
  2277.      "BaseStats"=>[10,"uuuuuu"],
  2278.      "Rareness"=>[16,"u"],
  2279.      "GenderRate"=>[18,"e",{"AlwaysMale"=>0,"FemaleOneEighth"=>31,"Female25Percent"=>63,
  2280.         "Female50Percent"=>127,"Female75Percent"=>191,"AlwaysFemale"=>254,"Genderless"=>255}],
  2281.      "Happiness"=>[19,"u"],
  2282.      "GrowthRate"=>[20,"e",["Medium","Erratic","Fluctuating","Parabolic","Fast","Slow"]],
  2283.      "StepsToHatch"=>[21,"w"],
  2284.      "EffortPoints"=>[23,"uuuuuu"],
  2285.      "Compatibility"=>[31,"uu"],
  2286.      "Height"=>[33,"f"],
  2287.      "Weight"=>[35,"f"],
  2288.      "BaseEXP"=>[38,"w"],
  2289.   }
  2290.   optionaltypes={
  2291.      "BattlerPlayerY"=>[0,"i"],
  2292.      "BattlerEnemyY"=>[0,"i"],
  2293.      "BattlerAltitude"=>[0,"i"],
  2294.      "EggMoves"=>[0,"*E",PBMoves],
  2295.      "FormNames"=>[0,"S"],
  2296.      "RegionalNumbers"=>[0,"*w"],
  2297.      "Evolutions"=>[0,"*ses",nil,["Unknown",
  2298.         "Happiness","HappinessDay","HappinessNight","Level","Trade",
  2299.         "TradeItem","Item","AttackGreater","AtkDefEqual","DefenseGreater",
  2300.         "Silcoon","Cascoon","Ninjask","Shedinja","Beauty",
  2301.         "ItemMale","ItemFemale","DayHoldItem","NightHoldItem","HasMove",
  2302.         "HasInParty","LevelMale","LevelFemale","Location","TradeSpecies",
  2303.         "happinessMoveType","typeDark","LevelRain","LevelDay","LevelNight","Custom6","Custom7"]],
  2304.      "Habitat"=>[7,"e",["","Grassland","Forest","WatersEdge","Sea","Cave","Mountain","RoughTerrain","Urban","Rare"]],
  2305.      "Type2"=>[9,"e",PBTypes],
  2306.      "Abilities"=>[29,"eg",PBAbilities,PBAbilities],
  2307.      "HiddenAbility"=>[40,"eggg",PBAbilities,PBAbilities,PBAbilities,PBAbilities],
  2308.      "WildItemCommon"=>[48,"*E",PBItems],
  2309.      "WildItemUncommon"=>[50,"*E",PBItems],
  2310.      "WildItemRare"=>[52,"*E",PBItems]
  2311.   }
  2312.   currentmap=-1
  2313.   dexdatas=[]
  2314.   eggmoves=[]
  2315.   entries=[]
  2316.   kinds=[]
  2317.   speciesnames=[]
  2318.   moves=[]
  2319.   evolutions=[]
  2320.   regionals=[]
  2321.   formnames=[]
  2322.   metrics=[SignedWordArray.new,SignedWordArray.new,SignedWordArray.new]
  2323.   constants=""
  2324.   maxValue=0
  2325.   File.open("PBS/pokemon.txt","rb"){|f|
  2326.      FileLineData.file="PBS/pokemon.txt"
  2327.      pbEachFileSection(f){|lastsection,currentmap|
  2328.         dexdata=[]
  2329.         for i in 0...76
  2330.           dexdata[i]=0
  2331.         end
  2332.         thesemoves=[]
  2333.         theseevos=[]
  2334.         if !lastsection["Type2"] || lastsection["Type2"]==""
  2335.           if !lastsection["Type1"] || lastsection["Type1"]==""
  2336.             raise _INTL("No Pokémon type is defined in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
  2337.             next
  2338.           end
  2339.           lastsection["Type2"]=lastsection["Type1"].clone
  2340.         end
  2341.         [requiredtypes,optionaltypes].each{|hash|
  2342.            for key in hash.keys
  2343.              FileLineData.setSection(currentmap+1,key,lastsection[key])
  2344.              maxValue=[maxValue,currentmap].max
  2345.              sectionDisplay=currentmap.to_s
  2346.              next if hash[key][0]<0
  2347.              if currentmap==0
  2348.                raise _INTL("A Pokemon species can't be numbered 0 (PBS/pokemon.txt)")
  2349.              end
  2350.              if !lastsection[key] || lastsection[key]==""
  2351.                raise _INTL("Required entry {1} is missing or empty in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
  2352.                next
  2353.              end
  2354.              secvalue=lastsection[key]
  2355.              rtschema=hash[key]
  2356.              schema=hash[key][1]
  2357.              valueindex=0
  2358.              loop do
  2359.                offset=0
  2360.                for i in 0...schema.length
  2361.                  next if schema[i,1]=="*"
  2362.                  minus1=(schema[0,1]=="*") ? -1 : 0
  2363.                  if schema[i,1]=="g" && secvalue==""
  2364.                    break
  2365.                  end
  2366.                  case schema[i,1]
  2367.                    when "e", "g"
  2368.                      value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
  2369.                      bytes=1
  2370.                    when "E"
  2371.                      value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
  2372.                      bytes=2
  2373.                    when "i"
  2374.                      value=csvInt!(secvalue,key)
  2375.                      bytes=1
  2376.                    when "u"
  2377.                      value=csvPosInt!(secvalue,key)
  2378.                      bytes=1
  2379.                    when "w"
  2380.                      value=csvPosInt!(secvalue,key)
  2381.                      bytes=2
  2382.                    when "f"
  2383.                      value=csvFloat!(secvalue,key,sectionDisplay)
  2384.                      value=(value*10).round
  2385.                      if value<=0
  2386.                        raise _INTL("Value '{1}' can't be less than or close to 0 (section {2}, PBS/pokemon.txt)",key,currentmap)
  2387.                      end
  2388.                      bytes=2
  2389.                    when "c", "s"
  2390.                      value=csvfield!(secvalue)
  2391.                    when "S"
  2392.                      value=secvalue
  2393.                      secvalue=""
  2394.                  end
  2395.                  if key=="EggMoves"
  2396.                    eggmoves[currentmap]=[] if !eggmoves[currentmap]
  2397.                    eggmoves[currentmap].push(value)
  2398.                  elsif key=="Moves"
  2399.                    thesemoves.push(value)
  2400.                  elsif key=="RegionalNumbers"
  2401.                    regionals[valueindex]=[] if !regionals[valueindex]
  2402.                    regionals[valueindex][currentmap]=value
  2403.                  elsif key=="Evolutions"
  2404.                    theseevos.push(value)
  2405.                  elsif key=="InternalName"
  2406.                    raise _INTL("Invalid internal name: {1} (section {2}, PBS/pokemon.txt)",value,currentmap) if !value[/^(?![0-9])\w*$/]
  2407.                    constants+="#{value}=#{currentmap}\r\n"
  2408.                  elsif key=="Kind"
  2409.                    raise _INTL("Kind {1} is greater than 13 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>13
  2410.                    kinds[currentmap]=value
  2411.                  elsif key=="Pokedex"
  2412.                    entries[currentmap]=value
  2413.                  elsif key=="BattlerPlayerY"
  2414.                    pbCheckSignedWord(value,key)
  2415.                    metrics[0][currentmap]=value
  2416.                  elsif key=="BattlerEnemyY"
  2417.                    pbCheckSignedWord(value,key)
  2418.                    metrics[1][currentmap]=value
  2419.                  elsif key=="BattlerAltitude"
  2420.                    pbCheckSignedWord(value,key)
  2421.                    metrics[2][currentmap]=value
  2422.                  elsif key=="Name"
  2423.                    raise _INTL("Species name {1} is greater than 20 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>20
  2424.                    speciesnames[currentmap]=value
  2425.                  elsif key=="FormNames"
  2426.                    formnames[currentmap]=value
  2427.                  else
  2428.                    dexdata[rtschema[0]+offset]=value&0xFF
  2429.                    dexdata[rtschema[0]+1+offset]=(value>>8)&0xFF if bytes>1
  2430.                    offset+=bytes
  2431.                  end
  2432.                  valueindex+=1
  2433.                end
  2434.                break if secvalue==""
  2435.                break if schema[0,1]!="*"
  2436.              end
  2437.            end
  2438.         }
  2439.         movelist=[]
  2440.         evolist=[]
  2441.         for i in 0...thesemoves.length/2
  2442.           movelist.push([thesemoves[i*2],thesemoves[i*2+1],i])
  2443.         end
  2444.         movelist.sort!{|a,b| a[0]==b[0] ? a[2]<=>b[2] : a[0]<=>b[0]}
  2445.         for i in movelist; i.pop; end
  2446.         for i in 0...theseevos.length/3
  2447.           evolist.push([theseevos[i*3],theseevos[i*3+1],theseevos[i*3+2]])
  2448.         end
  2449.         moves[currentmap]=movelist
  2450.         evolutions[currentmap]=evolist
  2451.         dexdatas[currentmap]=dexdata
  2452.      }
  2453.   }
  2454.   if dexdatas.length==0
  2455.     raise _INTL("No Pokémon species are defined in pokemon.txt")
  2456.   end
  2457.   count=dexdatas.compact.length
  2458.   code="module PBSpecies\r\n#{constants}"
  2459.   for i in 0...speciesnames.length
  2460.     speciesnames[i]="????????" if !speciesnames[i]
  2461.   end
  2462.   code+="def PBSpecies.getName(id)\r\nreturn pbGetMessage(MessageTypes::Species,id)\r\nend\r\n"
  2463.   code+="def PBSpecies.getCount\r\nreturn #{count}\r\nend\r\n"
  2464.   code+="def PBSpecies.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  2465.   eval(code)
  2466.   pbAddScript(code,"PBSpecies")
  2467.   for e in 0...evolutions.length
  2468.     evolist=evolutions[e]
  2469.     next if !evolist
  2470.     for i in 0...evolist.length
  2471.       FileLineData.setSection(i,"Evolutions","")
  2472.       evonib=evolist[i][1]
  2473.       evoparams=[0,
  2474.          0,0,0,1,0,
  2475.          2,2,1,1,1,
  2476.          1,1,1,1,1,
  2477.          2,2,2,2,3,
  2478.          4,1,1,1,4,
  2479.          3,1,1,1,1,5,5]
  2480.       evolist[i][0]=csvEnumField!(evolist[i][0],PBSpecies,"Evolutions",i)
  2481.       case evoparams[evonib]
  2482.         when 1
  2483.           evolist[i][2]=csvPosInt!(evolist[i][2])
  2484.         when 2
  2485.           evolist[i][2]=csvEnumField!(evolist[i][2],PBItems,"Evolutions",i)
  2486.         when 3
  2487.           evolist[i][2]=csvEnumField!(evolist[i][2],PBMoves,"Evolutions",i)
  2488.         when 4
  2489.           evolist[i][2]=csvEnumField!(evolist[i][2],PBSpecies,"Evolutions",i)
  2490.         when 5
  2491.           evolist[i][2]=csvPosInt!(evolist[i][2])
  2492.         else
  2493.           evolist[i][2]=0
  2494.       end
  2495.       evolist[i][3]=0
  2496.     end
  2497.   end
  2498.   _EVODATAMASK=0xC0
  2499.   _EVONEXTFORM=0x00
  2500.   _EVOPREVFORM=0x40
  2501.   for e in 0...evolutions.length
  2502.     evolist=evolutions[e]
  2503.     next if !evolist
  2504.     parent=nil
  2505.     child=-1
  2506.     for f in 0...evolutions.length
  2507.       evolist=evolutions[f]
  2508.       next if !evolist || e==f
  2509.       for g in evolist
  2510.         if g[0]==e && (g[3]&_EVODATAMASK)==_EVONEXTFORM
  2511.           parent=g
  2512.           child=f
  2513.           break
  2514.         end
  2515.       end
  2516.       break if parent
  2517.     end
  2518.     if parent
  2519.       evolutions[e]=[[child,parent[1],parent[2],_EVOPREVFORM]].concat(evolutions[e])
  2520.     end
  2521.   end
  2522.   metrics[0].fillNils(dexdatas.length,0) # player Y
  2523.   metrics[1].fillNils(dexdatas.length,0) # enemy Y
  2524.   metrics[2].fillNils(dexdatas.length,0) # altitude
  2525.   save_data(metrics,"Data/metrics.dat")
  2526.   File.open("Data/regionals.dat","wb"){|f|
  2527.      f.fputw(regionals.length)
  2528.      f.fputw(dexdatas.length)
  2529.      for i in 0...regionals.length
  2530.        for j in 0...dexdatas.length
  2531.          num=regionals[i][j]
  2532.          num=0 if !num
  2533.          f.fputw(num)
  2534.        end
  2535.      end
  2536.   }
  2537.   File.open("Data/evolutions.dat","wb"){|f|
  2538.      mx=[maxValue,evolutions.length-1].max
  2539.      offset=mx*8
  2540.      for i in 1..mx
  2541.        f.fputdw(offset)
  2542.        f.fputdw(evolutions[i] ? evolutions[i].length*5 : 0)
  2543.        offset+=evolutions[i] ? evolutions[i].length*5 : 0
  2544.      end
  2545.      for i in 1..mx
  2546.        next if !evolutions[i]
  2547.        for j in evolutions[i]
  2548.          f.fputb(j[3]|j[1])
  2549.          f.fputw(j[2])
  2550.          f.fputw(j[0])
  2551.        end
  2552.      end
  2553.   }
  2554.   File.open("Data/dexdata.dat","wb"){|f|
  2555.      mx=[maxValue,dexdatas.length-1].max
  2556.      for i in 1..mx
  2557.        if dexdatas[i]
  2558.          dexdatas[i].each {|item| f.fputb(item)}
  2559.        else
  2560.          76.times { f.fputb(0) }
  2561.        end
  2562.      end
  2563.   }
  2564.   File.open("Data/eggEmerald.dat","wb"){|f|
  2565.      mx=[maxValue,eggmoves.length-1].max
  2566.      offset=mx*8
  2567.      for i in 1..mx
  2568.        f.fputdw(offset)
  2569.        f.fputdw(eggmoves[i] ? eggmoves[i].length : 0)
  2570.        offset+=eggmoves[i] ? eggmoves[i].length*2 : 0
  2571.      end
  2572.      for i in 1..mx
  2573.        next if !eggmoves[i]
  2574.        for j in eggmoves[i]
  2575.          f.fputw(j)
  2576.        end
  2577.      end
  2578.   }
  2579.   MessageTypes.setMessages(MessageTypes::Species,speciesnames)
  2580.   MessageTypes.setMessages(MessageTypes::Kinds,kinds)
  2581.   MessageTypes.setMessages(MessageTypes::Entries,entries)
  2582.   MessageTypes.setMessages(MessageTypes::FormNames,formnames)
  2583.   File.open("Data/attacksRS.dat","wb"){|f|
  2584.      mx=[maxValue,moves.length-1].max
  2585.      offset=mx*8
  2586.      for i in 1..mx
  2587.        f.fputdw(offset)
  2588.        f.fputdw(moves[i] ? moves[i].length*2 : 0)
  2589.        offset+=moves[i] ? moves[i].length*4 : 0
  2590.      end
  2591.      for i in 1..mx
  2592.        next if !moves[i]
  2593.        for j in moves[i]
  2594.          f.fputw(j[0])
  2595.          f.fputw(j[1])
  2596.        end
  2597.      end
  2598.   }
  2599. end
  2600.  
  2601. datafiles=[
  2602.    "encounters.dat",
  2603.    "trainertypes.dat",
  2604.    "connections.dat",
  2605.    "items.dat",
  2606.    "metadata.dat",
  2607.    "townmap.dat",
  2608.    "trainers.dat",
  2609.    "attacksRS.dat",
  2610.    "dexdata.dat",
  2611.    "eggEmerald.dat",
  2612.    "evolutions.dat",
  2613.    "regionals.dat",
  2614.    "types.dat",
  2615.    "tm.dat",
  2616.    "phone.dat",
  2617.    "trainerlists.dat",
  2618.    "shadowmoves.dat",
  2619.    "contestmoves.dat",
  2620.    "Constants.rxdata"
  2621. ]
  2622.  
  2623. textfiles=[
  2624.    "moves.txt",
  2625.    "abilities.txt",
  2626.    "encounters.txt",
  2627.    "trainers.txt",
  2628.    "trainertypes.txt",
  2629.    "items.txt",
  2630.    "connections.txt",
  2631.    "metadata.txt",
  2632.    "townmap.txt",
  2633.    "pokemon.txt",
  2634.    "phone.txt",
  2635.    "trainerlists.txt",
  2636.    "shadowmoves.txt",
  2637.    "tm.txt",
  2638.    "contestmoves.txt",
  2639.    "types.txt"
  2640. ]
  2641.  
  2642. begin
  2643.  
  2644. def pbGenerateMoveRoute(commands)
  2645.   route=RPG::MoveRoute.new
  2646.   route.repeat=false
  2647.   route.skippable=true
  2648.   route.list.clear
  2649.   i=0;while i<commands.length
  2650.     case commands[i]
  2651.       when PBMoveRoute::Wait, PBMoveRoute::SwitchOn,
  2652.            PBMoveRoute::SwitchOff, PBMoveRoute::ChangeSpeed,
  2653.            PBMoveRoute::ChangeFreq, PBMoveRoute::Opacity,
  2654.            PBMoveRoute::Blending, PBMoveRoute::PlaySE,
  2655.            PBMoveRoute::Script
  2656.         route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1]]))
  2657.         i+=1
  2658.       when PBMoveRoute::ScriptAsync
  2659.         route.list.push(RPG::MoveCommand.new(PBMoveRoute::Script,[commands[i+1]]))
  2660.         route.list.push(RPG::MoveCommand.new(PBMoveRoute::Wait,[0]))
  2661.         i+=1
  2662.       when PBMoveRoute::Jump
  2663.         route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2]]))
  2664.         i+=2
  2665.       when PBMoveRoute::Graphic
  2666.         route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2],commands[i+3],commands[i+4]]))
  2667.         i+=4
  2668.       else
  2669.         route.list.push(RPG::MoveCommand.new(commands[i]))
  2670.     end
  2671.     i+=1
  2672.   end
  2673.   route.list.push(RPG::MoveCommand.new(0))
  2674.   return route
  2675. end
  2676.  
  2677. def pbPushMoveRoute(list,character,route,indent=0)
  2678.   if route.is_a?(Array)
  2679.     route=pbGenerateMoveRoute(route)
  2680.   end
  2681.   for i in 0...route.list.length
  2682.     list.push(RPG::EventCommand.new(
  2683.        i==0 ? 209 : 509,indent,
  2684.        i==0 ? [character,route] : [route.list[i-1]]))
  2685.   end
  2686. end
  2687.  
  2688. def pbPushMoveRouteAndWait(list,character,route,indent=0)
  2689.   pbPushMoveRoute(list,character,route,indent)
  2690.   pbPushEvent(list,210,[],indent)
  2691. end
  2692.  
  2693. def pbPushWait(list,frames,indent=0)
  2694.   pbPushEvent(list,106,[frames],indent)
  2695. end
  2696.  
  2697. def pbPushEvent(list,cmd,params=nil,indent=0)
  2698.   list.push(RPG::EventCommand.new(cmd,indent,params ? params : []))
  2699. end
  2700.  
  2701. def pbPushEnd(list)
  2702.   list.push(RPG::EventCommand.new(0,0,[]))
  2703. end
  2704.  
  2705. def pbPushComment(list,cmt,indent=0)
  2706.   textsplit2=cmt.split(/\n/)
  2707.   for i in 0...textsplit2.length
  2708.     list.push(RPG::EventCommand.new(i==0 ? 108 : 408,indent,[textsplit2[i].gsub(/\s+$/,"")]))
  2709.   end
  2710. end
  2711.  
  2712. def pbPushText(list,text,indent=0)
  2713.   return if !text
  2714.   textsplit=text.split(/\\m/)
  2715.   for t in textsplit
  2716.     first=true
  2717.     if $RPGVX
  2718.       list.push(RPG::EventCommand.new(101,indent,["",0,0,2]))
  2719.       first=false
  2720.     end
  2721.     textsplit2=t.split(/\n/)
  2722.     for i in 0...textsplit2.length
  2723.       textchunk=textsplit2[i].gsub(/\s+$/,"")
  2724.       if textchunk && textchunk!=""
  2725.         list.push(RPG::EventCommand.new(first ? 101 : 401,indent,[textchunk]))
  2726.         first=false
  2727.       end
  2728.     end
  2729.   end
  2730. end
  2731.  
  2732. def pbPushScript(list,script,indent=0)
  2733.   return if !script
  2734.   first=true
  2735.   textsplit2=script.split(/\n/)
  2736.   for i in 0...textsplit2.length
  2737.     textchunk=textsplit2[i].gsub(/\s+$/,"")
  2738.     if textchunk && textchunk!=""
  2739.       list.push(RPG::EventCommand.new(first ? 355 : 655,indent,[textchunk]))
  2740.       first=false
  2741.     end
  2742.   end
  2743. end
  2744.  
  2745. def pbPushExit(list,indent=0)
  2746.   list.push(RPG::EventCommand.new(115,indent,[]))
  2747. end
  2748.  
  2749. def pbPushElse(list,indent=0)
  2750.   list.push(RPG::EventCommand.new(0,indent,[]))
  2751.   list.push(RPG::EventCommand.new(411,indent-1,[]))
  2752. end
  2753.  
  2754. def pbPushBranchEnd(list,indent=0)
  2755.   list.push(RPG::EventCommand.new(0,indent,[]))
  2756.   list.push(RPG::EventCommand.new(412,indent-1,[]))
  2757. end
  2758.  
  2759. def pbPushBranch(list,script,indent=0)
  2760.   list.push(RPG::EventCommand.new(111,indent,[12,script]))
  2761. end
  2762.  
  2763. def pbPushSelfSwitch(list,swtch,switchOn,indent=0)
  2764.   list.push(RPG::EventCommand.new(123,indent,[swtch,switchOn ? 0 : 1]))
  2765. end
  2766.  
  2767. def safequote(x)
  2768.   x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  2769.  x=x.gsub(/\t/,"\\t")
  2770.  x=x.gsub(/\r/,"\\r")
  2771.  x=x.gsub(/\n/,"\\n")
  2772.  return x
  2773. end
  2774.  
  2775. def safequote2(x)
  2776.  x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  2777.  x=x.gsub(/\t/,"\\t")
  2778.  x=x.gsub(/\r/,"\\r")
  2779.  x=x.gsub(/\n/," ")
  2780.  return x
  2781. end
  2782.  
  2783. def pbEventId(event)
  2784.  list=event.pages[0].list
  2785.  return nil if list.length==0
  2786.  codes=[]
  2787.  i=0;while i<list.length
  2788.    codes.push(list[i].code)
  2789.    i+=1
  2790.  end
  2791. end
  2792.  
  2793.  
  2794.  
  2795. class MapData
  2796.  def initialize
  2797.    @mapinfos=pbLoadRxData("Data/MapInfos")
  2798.    @system=pbLoadRxData("Data/System")
  2799.    @tilesets=pbLoadRxData("Data/Tilesets")
  2800.    @mapxy=[]
  2801.    @mapWidths=[]
  2802.    @mapHeights=[]
  2803.    @maps=[]
  2804.    @registeredSwitches={}
  2805.  end
  2806.  
  2807.  def registerSwitch(switch)
  2808.    if @registeredSwitches[switch]
  2809.      return @registeredSwitches[switch]
  2810.    end
  2811.    for id in 1..5000
  2812.      name=@system.switches[id]
  2813.      if !name || name=="" || name==switch
  2814.        @system.switches[id]=switch
  2815.        @registeredSwitches[switch]=id
  2816.        return id
  2817.      end
  2818.    end
  2819.    return 1
  2820.  end
  2821.  
  2822.  def saveTilesets
  2823.    filename="Data/Tilesets"
  2824.    if $RPGVX
  2825.      filename+=".rvdata"
  2826.    else
  2827.      filename+=".rxdata"
  2828.    end
  2829.    save_data(@tilesets,filename)
  2830.    filename="Data/System"
  2831.    if $RPGVX
  2832.      filename+=".rvdata"
  2833.    else
  2834.      filename+=".rxdata"
  2835.    end
  2836.    save_data(@system,filename)
  2837.  end
  2838.  
  2839.  def switchName(id)
  2840.    return @system.switches[id] || ""
  2841.  end
  2842.  
  2843.  def mapFilename(mapID)
  2844.    filename=sprintf("Data/map%03d",mapID)
  2845.    if $RPGVX
  2846.      filename+=".rvdata"
  2847.    else
  2848.      filename+=".rxdata"
  2849.    end
  2850.    return filename
  2851.  end
  2852.  
  2853.  def getMap(mapID)
  2854.    if @maps[mapID]
  2855.      return @maps[mapID]
  2856.    else
  2857.      begin
  2858.        @maps[mapID]=load_data(mapFilename(mapID))
  2859.        return @maps[mapID]
  2860.        rescue
  2861.        return nil
  2862.      end
  2863.    end
  2864.  end
  2865.  
  2866.  def isPassable?(mapID,x,y)
  2867.    if !$RPGVX
  2868.      map=getMap(mapID)
  2869.      return false if !map
  2870.      return false if x<0 || x>=map.width || y<0 || y>=map.height
  2871.      passages=@tilesets[map.tileset_id].passages
  2872.      priorities=@tilesets[map.tileset_id].priorities
  2873.      for i in [2, 1, 0]
  2874.        tile_id = map.data[x, y, i]
  2875.        return false if tile_id == nil
  2876.        return false if passages[tile_id] & 0x0f == 0x0f
  2877.        return true if priorities[tile_id] == 0
  2878.      end
  2879.    end
  2880.    return true
  2881.  end
  2882.  
  2883.  def setCounterTile(mapID,x,y)
  2884.    if !$RPGVX
  2885.      map=getMap(mapID)
  2886.      return if !map
  2887.      passages=@tilesets[map.tileset_id].passages
  2888.      for i in [2, 1, 0]
  2889.        tile_id = map.data[x, y, i]
  2890.        next if tile_id == 0 || tile_id==nil || !passages[tile_id]
  2891.        passages[tile_id]|=0x80
  2892.        break
  2893.      end
  2894.    end
  2895.  end
  2896.  
  2897.  def isCounterTile?(mapID,x,y)
  2898.    return false if $RPGVX
  2899.    map=getMap(mapID)
  2900.    return false if !map
  2901.    passages=@tilesets[map.tileset_id].passages
  2902.    for i in [2, 1, 0]
  2903.      tile_id = map.data[x, y, i]
  2904.      return false if tile_id == nil
  2905.      return true if passages[tile_id] && passages[tile_id] & 0x80 == 0x80
  2906.    end
  2907.    return false
  2908.  end
  2909.  
  2910.  def saveMap(mapID)
  2911.    save_data(getMap(mapID),mapFilename(mapID)) rescue nil
  2912.  end
  2913.  
  2914.  def getEventFromXY(mapID,x,y)
  2915.    return nil if x<0 || y<0
  2916.    mapPositions=@mapxy[mapID]
  2917.    if mapPositions
  2918.      return mapPositions[y*@mapWidths[mapID]+x]
  2919.    else
  2920.      map=getMap(mapID)
  2921.      return nil if !map
  2922.      @mapWidths[mapID]=map.width
  2923.      @mapHeights[mapID]=map.height
  2924.      mapPositions=[]
  2925.      width=map.width
  2926.      for e in map.events.values
  2927.        mapPositions[e.y*width+e.x]=e if e
  2928.      end
  2929.      @mapxy[mapID]=mapPositions
  2930.      return mapPositions[y*width+x]
  2931.    end
  2932.  end
  2933.  
  2934.  def getEventFromID(mapID,id)
  2935.    map=getMap(mapID)
  2936.    return nil if !map
  2937.    return map.events[id]
  2938.  end
  2939.  
  2940.  def mapinfos
  2941.    return @mapinfos
  2942.  end
  2943. end
  2944.  
  2945.  
  2946.  
  2947. class TrainerChecker
  2948.  def initialize
  2949.    @trainers=nil
  2950.    @trainertypes=nil
  2951.    @dontaskagain=false
  2952.  end
  2953.  
  2954.  def pbTrainerTypeCheck(symbol)
  2955.    ret=true
  2956.    if $DEBUG  
  2957.      return if @dontaskagain
  2958.      if !hasConst?(PBTrainers,symbol)
  2959.        ret=false
  2960.      else
  2961.        trtype=PBTrainers.const_get(symbol)
  2962.        @trainertypes=load_data("Data/trainertypes.dat") if !@trainertypes
  2963.        if !@trainertypes || !@trainertypes[trtype]    
  2964.          ret=false  
  2965.        end
  2966.      end  
  2967.      if !ret
  2968.        if Kernel.pbConfirmMessage(_INTL("Add new trainer named {1}?",symbol))
  2969.          pbTrainerTypeEditorNew(symbol.to_s)
  2970.          @trainers=nil
  2971.          @trainertypes=nil
  2972.        end
  2973. #        if pbMapInterpreter
  2974. #          pbMapInterpreter.command_end rescue nil
  2975. #        end
  2976.      end
  2977.    end
  2978.    return ret
  2979.  end
  2980.  
  2981.  def pbTrainerBattleCheck(trtype,trname,trid)
  2982.    if $DEBUG
  2983.      return if @dontaskagain
  2984.      if trtype.is_a?(String) || trtype.is_a?(Symbol)
  2985.        pbTrainerTypeCheck(trtype)
  2986.        return if !hasConst?(PBTrainers,trtype)
  2987.        trtype=PBTrainers.const_get(trtype)
  2988.      end
  2989.      @trainers=load_data("Data/trainers.dat") if !@trainers
  2990.      if @trainers
  2991.        for trainer in @trainers
  2992.          name=trainer[1]
  2993.          thistrainerid=trainer[0]
  2994.          thispartyid=trainer[4]
  2995.          next if name!=trname || thistrainerid!=trtype || thispartyid!=trid
  2996.          return
  2997.        end
  2998.      end
  2999.      cmd=pbMissingTrainer(trtype,trname,trid)
  3000.      if cmd==2
  3001.        @dontaskagain=true
  3002.        Graphics.update
  3003.      end
  3004.      @trainers=nil
  3005.      @trainertypes=nil
  3006.    end
  3007.  end
  3008. end
  3009.  
  3010.  
  3011.  
  3012. def pbCompileTrainerEvents(mustcompile)
  3013.  mapdata=MapData.new
  3014.  t = Time.now.to_i
  3015.  Graphics.update
  3016.  trainerChecker=TrainerChecker.new
  3017.  for id in mapdata.mapinfos.keys.sort
  3018.    changed=false
  3019.    map=mapdata.getMap(id)
  3020.    next if !map || !mapdata.mapinfos[id]
  3021.    Win32API.SetWindowText(_INTL("Processing map {1} ({2})",id,mapdata.mapinfos[id].name))
  3022.    for key in map.events.keys
  3023.      if Time.now.to_i - t >= 5
  3024.        Graphics.update
  3025.        t = Time.now.to_i
  3026.      end
  3027.      newevent=pbConvertToTrainerEvent(map.events[key],trainerChecker)
  3028.      if newevent
  3029.        changed=true
  3030.        map.events[key]=newevent
  3031.      end
  3032.      newevent=pbConvertToItemEvent(map.events[key])
  3033.      if newevent
  3034.        changed=true
  3035.        map.events[key]=newevent
  3036.      end
  3037.      newevent=pbFixEventUse(map.events[key],id,mapdata)
  3038.      if newevent
  3039.        changed=true
  3040.        map.events[key]=newevent
  3041.      end
  3042.    end
  3043.    if Time.now.to_i - t >= 5
  3044.      Graphics.update
  3045.      t = Time.now.to_i
  3046.    end
  3047.    changed=true if pbCheckCounters(map,id,mapdata)
  3048.    if changed
  3049.      mapdata.saveMap(id)
  3050.      mapdata.saveTilesets
  3051.    end
  3052.  end
  3053.  changed=false
  3054.  if Time.now.to_i-t>=5
  3055.    Graphics.update
  3056.    t=Time.now.to_i
  3057.  end
  3058.  commonEvents=pbLoadRxData("Data/CommonEvents")
  3059.  Win32API.SetWindowText(_INTL("Processing common events"))
  3060.  for key in 0...commonEvents.length
  3061.    newevent=pbFixEventUse(commonEvents[key],0,mapdata)
  3062.    if newevent
  3063.      changed=true
  3064.      map.events[key]=newevent
  3065.    end
  3066.  end
  3067.  if changed
  3068.    if $RPGVX
  3069.      save_data(commonEvents,"Data/CommonEvents.rvdata")
  3070.    else
  3071.      save_data(commonEvents,"Data/CommonEvents.rxdata")
  3072.    end
  3073.  end
  3074.  if !$RPGVX && $INTERNAL
  3075. #   convertVXProject(mapdata)
  3076.  end
  3077. end
  3078.  
  3079. def isPlainEvent?(event)
  3080.  return event && event.pages.length<=1 &&
  3081.         event.pages[0].list.length<=1 &&
  3082.         event.pages[0].move_type==0 &&
  3083.         event.pages[0].condition.switch1_valid==false &&
  3084.         event.pages[0].condition.switch2_valid==false &&
  3085.         event.pages[0].condition.variable_valid==false &&
  3086.         event.pages[0].condition.self_switch_valid==false
  3087. end
  3088.  
  3089. def isPlainEventOrMart?(event)
  3090.  return event &&
  3091.         event.pages.length<=1 &&
  3092.         event.pages[0].move_type==0 &&
  3093.         event.pages[0].condition.switch1_valid==false &&
  3094.         event.pages[0].condition.switch2_valid==false &&
  3095.         event.pages[0].condition.variable_valid==false &&
  3096.         event.pages[0].condition.self_switch_valid==false &&
  3097.         ((event.pages[0].list.length<=1) || (
  3098.         event.pages[0].list.length<=12 &&
  3099.         event.pages[0].graphic.character_name!="" &&
  3100.         event.pages[0].list[0].code==355 &&
  3101.         event.pages[0].list[0].parameters[0][/^pbPokemonMart/]) || (
  3102.         event.pages[0].list.length>8 &&
  3103.         event.pages[0].graphic.character_name!="" &&
  3104.         event.pages[0].list[0].code==355 &&
  3105.         event.pages[0].list[0].parameters[0][/^Kernel\.pbSetPokemonCenter/])
  3106.         )
  3107. end
  3108.  
  3109. def applyPages(page,pages)
  3110.  for p in pages
  3111.    p.graphic=page.graphic
  3112.    p.walk_anime=page.walk_anime
  3113.    p.step_anime=page.step_anime
  3114.    p.direction_fix=page.direction_fix
  3115.    p.through=page.through
  3116.    p.always_on_top=page.always_on_top
  3117.  end
  3118. end
  3119.  
  3120. def isLikelyCounter?(thisEvent,otherEvent,mapID,mapdata)
  3121.  # Check whether other event is likely on a counter tile
  3122.  yonderX=otherEvent.x+(otherEvent.x-thisEvent.x)
  3123.  yonderY=otherEvent.y+(otherEvent.y-thisEvent.y)
  3124.  return true if mapdata.isCounterTile?(mapID,otherEvent.x,otherEvent.y)
  3125.  return thisEvent.pages[0].graphic.character_name!="" &&
  3126.         otherEvent.pages[0].graphic.character_name=="" &&
  3127.         otherEvent.pages[0].trigger==0 &&
  3128.         mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
  3129.         !mapdata.isPassable?(mapID,otherEvent.x,otherEvent.y) &&
  3130.         mapdata.isPassable?(mapID,yonderX,yonderY)
  3131. end
  3132.  
  3133. def isLikelyPassage?(thisEvent,mapID,mapdata)
  3134.  return false if !thisEvent || thisEvent.pages.length==0
  3135.  return false if thisEvent.pages.length!=1
  3136.  if thisEvent.pages[0].graphic.character_name=="" &&
  3137.     thisEvent.pages[0].list.length<=12 &&
  3138.     thisEvent.pages[0].list.any? {|cmd| cmd.code==201 } &&
  3139. #     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y+1) &&
  3140.     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
  3141.     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y) &&
  3142.     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y) &&
  3143.     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y-1) &&
  3144.     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y-1)
  3145.    return true
  3146.  else
  3147.    return false
  3148.  end
  3149. end
  3150.  
  3151. def pbCheckCounters(map,mapID,mapdata)
  3152.  todelete=[]
  3153.  changed=false
  3154.  for key in map.events.keys
  3155.    event=map.events[key]
  3156.    next if !event
  3157.    firstCommand=event.pages[0].list[0]
  3158.    if isPlainEventOrMart?(event)
  3159.      # Empty event, check for counter events
  3160.      neighbors=[]
  3161.      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y-1))
  3162.      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y+1))
  3163.      neighbors.push(mapdata.getEventFromXY(mapID,event.x-1,event.y))
  3164.      neighbors.push(mapdata.getEventFromXY(mapID,event.x+1,event.y))
  3165.      neighbors.compact!
  3166.      for otherEvent in neighbors
  3167.        next if isPlainEvent?(otherEvent)
  3168.        if isLikelyCounter?(event,otherEvent,mapID,mapdata)
  3169.          mapdata.setCounterTile(mapID,otherEvent.x,otherEvent.y)
  3170.          savedPage=event.pages[0]
  3171.          event.pages=otherEvent.pages
  3172.          applyPages(savedPage,event.pages)
  3173.          todelete.push(otherEvent.id)
  3174.          changed=true
  3175.        end
  3176.      end
  3177.    end
  3178.  end
  3179.  for key in todelete
  3180.    map.events.delete(key)
  3181.  end
  3182.  return changed
  3183. end
  3184.  
  3185. def pbAddPassageList(event,mapdata)
  3186.  return if !event || event.pages.length==0
  3187.  page=RPG::Event::Page.new
  3188.  page.condition.switch1_valid=true
  3189.  page.condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3190.  page.graphic.character_name=""
  3191.  page.trigger=3 # Autorun
  3192.  page.list.clear
  3193.  list=page.list
  3194.  pbPushBranch(list,"get_character(0).onEvent?")
  3195.  pbPushEvent(list,208,[0],1)
  3196.  pbPushWait(list,6,1)
  3197.  pbPushEvent(list,208,[1],1)
  3198.  pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
  3199.  pbPushBranchEnd(list,1)
  3200.  pbPushScript(list,"setTempSwitchOn(\"A\")")
  3201.   pbPushEnd(list)
  3202.   event.pages.push(page)
  3203. end
  3204.  
  3205. def pbUpdateDoor(event,mapdata)
  3206.   changed=false
  3207.   return false if event.is_a?(RPG::CommonEvent)
  3208.   if event.pages.length>=2 &&
  3209.      event.pages[event.pages.length-1].condition.switch1_valid &&
  3210.      event.pages[event.pages.length-1].condition.switch1_id==12 &&
  3211.      event.pages[event.pages.length-1].list.length>5 &&
  3212.      event.pages[event.pages.length-1].graphic.character_name!="" &&
  3213.      mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
  3214.      event.pages[event.pages.length-1].list[0].code==111
  3215.     event.pages[event.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3216.     changed=true
  3217.   end
  3218.   if event.pages.length>=2 &&
  3219.      event.pages[event.pages.length-1].condition.switch1_valid &&
  3220.      event.pages[event.pages.length-1].list.length>5 &&
  3221.      event.pages[event.pages.length-1].graphic.character_name!="" &&
  3222.      mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)=='s:tsOff?("A")' &&
  3223.      event.pages[event.pages.length-1].list[0].code==111
  3224.     list=event.pages[event.pages.length-2].list
  3225.     transferCommand=list.find_all {|cmd| cmd.code==201 }
  3226.     if transferCommand.length==1 && !list.any?{|cmd| cmd.code==208 }
  3227.       list.clear
  3228.       pbPushMoveRouteAndWait(list,0,[
  3229.          PBMoveRoute::PlaySE,RPG::AudioFile.new("Entering Door"),PBMoveRoute::Wait,2,
  3230.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
  3231.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3232.          PBMoveRoute::TurnUp,PBMoveRoute::Wait,2])
  3233.       pbPushMoveRouteAndWait(list,-1,[
  3234.          PBMoveRoute::ThroughOn,PBMoveRoute::Up,PBMoveRoute::ThroughOff])
  3235.       pbPushEvent(list,208,[0]) # Change Transparent Flag
  3236.       pbPushMoveRouteAndWait(list,0,[PBMoveRoute::Wait,2,
  3237.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3238.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
  3239.          PBMoveRoute::TurnDown,PBMoveRoute::Wait,2])
  3240.       pbPushEvent(list,223,[Tone.new(-255,-255,-255),6])
  3241.       pbPushWait(list,8)
  3242.       pbPushEvent(list,208,[1])
  3243.       pbPushEvent(list,transferCommand[0].code,transferCommand[0].parameters)
  3244.       pbPushEvent(list,223,[Tone.new(0,0,0),6])
  3245.       pbPushEnd(list)
  3246.       list=event.pages[event.pages.length-1].list
  3247.       list.clear
  3248.       pbPushBranch(list,"get_character(0).onEvent?")
  3249.       pbPushEvent(list,208,[0],1)
  3250.       pbPushMoveRouteAndWait(list,0,[
  3251.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,6],1)
  3252.       pbPushEvent(list,208,[1],1)
  3253.       pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
  3254.       pbPushMoveRouteAndWait(list,0,[
  3255.          PBMoveRoute::TurnUp,PBMoveRoute::Wait,2,
  3256.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3257.          PBMoveRoute::TurnDown,PBMoveRoute::Wait,2],1)
  3258.       pbPushBranchEnd(list,1)
  3259.       pbPushScript(list,"setTempSwitchOn(\"A\")")
  3260.       pbPushEnd(list)
  3261.       changed=true
  3262.     end
  3263.   end
  3264.   return changed
  3265. end
  3266.  
  3267. def pbEventIsEmpty?(e)
  3268.   return true if !e
  3269.   if e.is_a?(RPG::CommonEvent)
  3270.     return false
  3271.   else
  3272.     return e.pages.length==0
  3273.   end
  3274. end
  3275.  
  3276. def pbEachPage(e)
  3277.   return true if !e
  3278.   if e.is_a?(RPG::CommonEvent)
  3279.     yield e
  3280.   else
  3281.     e.pages.each {|page| yield page }
  3282.   end
  3283. end
  3284.  
  3285. def pbChangeScript(script,re)
  3286.   tmp=script[0].gsub(re){ yield($~) }
  3287.   if script[0]!=tmp
  3288.     script[0]=tmp; return true
  3289.   end
  3290.   return false
  3291. end
  3292.  
  3293. def pbChangeScripts(script)
  3294.   changed=false
  3295.   changed|=pbChangeScript(script,/\$game_variables\[(\d+)\](?!\s*(?:\=|\!|<|>))/){|m| "pbGet("+m[1]+")" }
  3296.   changed|=pbChangeScript(script,/\$Trainer\.party\[\s*pbGet\((\d+)\)\s*\]/){|m| "pbGetPokemon("+m[1]+")" }
  3297.   return changed
  3298. end
  3299.  
  3300. def pbFixEventUse(event,mapID,mapdata)
  3301.   return nil if pbEventIsEmpty?(event)
  3302.   changed=false
  3303.   trainerMoneyRE=/^\s*\$Trainer\.money\s*(<|<=|>|>=)\s*(\d+)\s*$/
  3304.   itemBallRE=/^\s*(Kernel\.)?pbItemBall/
  3305.   if pbUpdateDoor(event,mapdata)
  3306.     changed=true
  3307.   end
  3308.   pbEachPage(event) do |page|
  3309.     i=0
  3310.     list=page.list
  3311.     while i<list.length
  3312.       params=list[i].parameters
  3313.       if list[i].code==655
  3314.         x=[params[0]]
  3315.         changed|=pbChangeScripts(x)
  3316.         params[0]=x[0]
  3317.       elsif list[i].code==355
  3318.         lastScript=i
  3319.         if !params[0].is_a?(String)
  3320.           i+=1
  3321.           next
  3322.         end
  3323.         x=[params[0]]
  3324.         changed|=pbChangeScripts(x)
  3325.         params[0]=x[0]
  3326.         if params[0][0,1]!="f" && params[0][0,1]!="p" && params[0][0,1]!="K"
  3327.           i+=1
  3328.           next
  3329.         end
  3330.         script=" "+params[0]
  3331.         j=i+1
  3332.         while j<list.length
  3333.           break if list[j].code!=655
  3334.           script+=list[j].parameters[0]
  3335.           lastScript=j
  3336.           j+=1
  3337.         end
  3338.         script.gsub!(/\s+/,"")
  3339.         # Using old method of recovering
  3340.         if script=="foriin$Trainer.partyi.healend"
  3341.           for j in i..lastScript
  3342.             list.delete_at(i)
  3343.           end
  3344.           list.insert(i,
  3345.              RPG::EventCommand.new(314,list[i].indent,[0]) # Recover All
  3346.           )
  3347.           changed=true
  3348.         elsif script=="pbFadeOutIn(99999){foriin$Trainer.partyi.healend}"
  3349.           oldIndent=list[i].indent
  3350.           for j in i..lastScript
  3351.             list.delete_at(i)
  3352.           end
  3353.           list.insert(i,
  3354.              RPG::EventCommand.new(223,oldIndent,[Tone.new(-255,-255,-255),6]), # Fade to black
  3355.              RPG::EventCommand.new(106,oldIndent,[6]), # Wait
  3356.              RPG::EventCommand.new(314,oldIndent,[0]), # Recover All
  3357.              RPG::EventCommand.new(223,oldIndent,[Tone.new(0,0,0),6]), # Fade to normal
  3358.              RPG::EventCommand.new(106,oldIndent,[6]) # Wait
  3359.           )
  3360.           changed=true
  3361.         end
  3362.       elsif list[i].code==108
  3363.         if params[0][/SellItem\s*\(\s*(\w+)\s*\,\s*(\d+)\s*\)/]
  3364.           itemname=$1
  3365.           cost=$2.to_i
  3366.           if hasConst?(PBItems,itemname)
  3367.             oldIndent=list[i].indent
  3368.             list.delete_at(i)
  3369.             newEvents=[]
  3370.             if cost==0
  3371.               pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent)
  3372.               pbPushText(newEvents,_INTL("Here you go!"),oldIndent+1)
  3373.               pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+1)
  3374.               pbPushElse(newEvents,oldIndent+1)
  3375.               pbPushText(newEvents,_INTL("You have no room left in the Bag."),oldIndent+1)
  3376.               pbPushBranchEnd(newEvents,oldIndent+1)
  3377.             else
  3378.               pbPushEvent(newEvents,111,[7,cost,0],oldIndent)
  3379.               pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent+1)
  3380.               pbPushEvent(newEvents,125,[1,0,cost],oldIndent+2)
  3381.               pbPushText(newEvents,_INTL("\\GHere you go!"),oldIndent+2)
  3382.               pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+2)
  3383.               pbPushElse(newEvents,oldIndent+2)
  3384.               pbPushText(newEvents,_INTL("\\GYou have no room left in the Bag."),oldIndent+2)
  3385.               pbPushBranchEnd(newEvents,oldIndent+2)
  3386.               pbPushElse(newEvents,oldIndent+1)
  3387.               pbPushText(newEvents,_INTL("\\GYou don't have enough money."),oldIndent+1)
  3388.               pbPushBranchEnd(newEvents,oldIndent+1)
  3389.             end
  3390.             list[i,0]=newEvents # insert 'newEvents' at index 'i'
  3391.             changed=true
  3392.           end
  3393.         end
  3394.       elsif list[i].code==115 && i==list.length-2
  3395.         # Superfluous exit command
  3396.         list.delete_at(i)
  3397.         changed=true
  3398.       elsif list[i].code==201 && list.length<=8
  3399.         if params[0]==0
  3400.           # Transfer back to door
  3401.           e=mapdata.getEventFromXY(params[1],params[2],params[3]-1)
  3402.           if e && e.pages.length>=2 &&
  3403.              e.pages[e.pages.length-1].condition.switch1_valid &&
  3404.              e.pages[e.pages.length-1].condition.switch1_id==12 &&
  3405.              mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
  3406.              e.pages[e.pages.length-1].list.length>5 &&
  3407.              e.pages[e.pages.length-1].list[0].code==111
  3408.             e.pages[e.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3409.             mapdata.saveMap(params[1])
  3410.             changed=true
  3411.          end
  3412.          if isLikelyPassage?(e,params[1],mapdata)
  3413.            pbAddPassageList(e,mapdata)
  3414.            mapdata.saveMap(params[1])
  3415.            changed=true
  3416.          end
  3417.          if e && e.pages.length>=2 &&
  3418.             e.pages[e.pages.length-1].condition.switch1_valid &&
  3419.             mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)=='s:tsOff?("A")'
  3420.            # If this is really a door, move transfer target to it
  3421.            params[3]-=1
  3422.            params[5]=1 # No fade
  3423.            changed=true
  3424.          end
  3425.          deletedRoute=nil
  3426.          deleteMoveRouteAt=proc{|list,_i|
  3427.             arr=[]
  3428.             if list[_i] && list[_i].code==209
  3429.               arr.push(list[_i]);list.delete_at(_i)
  3430.               while _i<list.length
  3431.                 break if !list[_i] || list[_i].code!=509
  3432.                 arr.push(list[_i]);list.delete_at(_i)    
  3433.               end
  3434.             end
  3435.             next arr
  3436.          }
  3437.          insertMoveRouteAt=proc{|list,_i,route|
  3438.             _j=route.length-1;while _j>=0
  3439.               list.insert(_i,route[_j])
  3440.             _j-=1;end
  3441.          }
  3442.          if params[4]==0 && # Retain direction
  3443.            i+1<list.length && list[i+1].code==209 && list[i+1].parameters[0]==-1
  3444.            route=list[i+1].parameters[1]
  3445.            if route && route.list.length<=2
  3446.              # Delete superfluous move route command if necessary
  3447.              if route.list[0].code==16 # Player/Turn Down
  3448.                deleteMoveRouteAt.call(list,i+1); params[4]=2; changed=true
  3449.              elsif route.list[0].code==17 # Left
  3450.                deleteMoveRouteAt.call(list,i+1); params[4]=4; changed=true
  3451.              elsif route.list[0].code==18 # Right
  3452.                deleteMoveRouteAt.call(list,i+1); params[4]=6; changed=true
  3453.              elsif route.list[0].code==19 # Up
  3454.                deleteMoveRouteAt.call(list,i+1); params[4]=8; changed=true
  3455.              elsif (route.list[0].code==1 || route.list[0].code==2 ||
  3456.                route.list[0].code==3 || route.list[0].code==4) && list.length==4
  3457.                params[4]=[0,2,4,6,8][route.list[0].code]
  3458.                deletedRoute=deleteMoveRouteAt.call(list,i+1); changed=true
  3459.              end
  3460.            end
  3461.          elsif params[4]==0 && i>3
  3462.            for j in 0...i
  3463.              if list[j].code==209 && list[j].parameters[0]==-1
  3464.                route=list[j].parameters[1]
  3465.                oldlistlength=list.length
  3466.                if route && route.list.length<=2
  3467.                  # Delete superfluous move route command if necessary
  3468.                  if route.list[0].code==16 # Player/Turn Down
  3469.                    deleteMoveRouteAt.call(list,j); params[4]=2; changed=true;i-=(oldlistlength-list.length)
  3470.                  elsif route.list[0].code==17 # Left
  3471.                    deleteMoveRouteAt.call(list,j); params[4]=4; changed=true;i-=(oldlistlength-list.length)
  3472.                  elsif route.list[0].code==18 # Right
  3473.                    deleteMoveRouteAt.call(list,j); params[4]=6; changed=true;i-=(oldlistlength-list.length)
  3474.                  elsif route.list[0].code==19 # Up
  3475.                    deleteMoveRouteAt.call(list,j); params[4]=8; changed=true;i-=(oldlistlength-list.length)
  3476.                  end
  3477.                end
  3478.              end
  3479.            end
  3480.          elsif params[4]==0 && # Retain direction
  3481.             i+2<list.length &&
  3482.             list[i+1].code==223 &&
  3483.             list[i+2].code==209 &&
  3484.             list[i+2].parameters[0]==-1
  3485.            route=list[i+2].parameters[1]
  3486.            if route && route.list.length<=2
  3487.              # Delete superfluous move route command if necessary
  3488.              if route.list[0].code==16 # Player/Turn Down
  3489.                deleteMoveRouteAt.call(list,i+2); params[4]=2; changed=true
  3490.              elsif route.list[0].code==17 # Left
  3491.                deleteMoveRouteAt.call(list,i+2); params[4]=4; changed=true
  3492.              elsif route.list[0].code==18 # Right
  3493.                deleteMoveRouteAt.call(list,i+2); params[4]=6; changed=true
  3494.              elsif route.list[0].code==19 # Up
  3495.                deleteMoveRouteAt.call(list,i+2); params[4]=8; changed=true
  3496.              end
  3497.            end
  3498.          end
  3499.        end
  3500.        # If this is the only event command, convert to a full event
  3501.        if list.length==2 || (list.length==3 && (list[0].code==250 || list[1].code==250))
  3502.          params[5]=1 # No fade
  3503.          fullTransfer=list[i]
  3504.          indent=list[i].indent
  3505.          (list.length-1).times { list.delete_at(0) }
  3506.            list.insert(0,
  3507.               RPG::EventCommand.new(250,indent,[RPG::AudioFile.new("Exit Door",80,100)]), # Play SE
  3508.               RPG::EventCommand.new(223,indent,[Tone.new(-255,-255,-255),6]), # Fade to black
  3509.               RPG::EventCommand.new(106,indent,[8]), # Wait
  3510.               fullTransfer, # Transfer event
  3511.               RPG::EventCommand.new(223,indent,[Tone.new(0,0,0),6]) # Fade to normal
  3512.            )
  3513.            changed=true
  3514.          end
  3515.          if deletedRoute
  3516.            insertMoveRouteAt.call(list,list.length-1,deletedRoute)
  3517.            changed=true
  3518.          end
  3519.        elsif list[i].code==101
  3520.          if list[i].parameters[0][0,1]=="\\"
  3521.            newx=list[i].parameters[0].clone
  3522.            newx.sub!(/^\\[Bb]\s+/,"\\b")
  3523.            newx.sub!(/^\\[Rr]\s+/,"\\r")
  3524.            newx.sub!(/^\\[Pp][Gg]\s+/,"\\pg")
  3525.            newx.sub!(/^\\[Pp][Oo][Gg]\s+/,"\\pog")
  3526.            newx.sub!(/^\\[Gg]\s+/,"\\G")
  3527.            newx.sub!(/^\\[Cc][Nn]\s+/,"\\CN")
  3528.            if list[i].parameters[0]!=newx
  3529.              list[i].parameters[0]=newx
  3530.              changed=true
  3531.            end
  3532.          end
  3533.          lines=1
  3534.          j=i+1; while j<list.length
  3535.            break if list[j].code!=401
  3536.            if lines%4==0
  3537.              list[j].code=101
  3538.              changed=true
  3539.            end
  3540.            lines+=1
  3541.            j+=1
  3542.          end
  3543.          if lines>=2 && list[i].parameters[0].length>0 && list[i].parameters[0].length<=20 &&
  3544.             !list[i].parameters[0][/\\n/]
  3545.            # Very short line
  3546.            list[i].parameters[0]+="\\n"+list[i+1].parameters[0]
  3547.            list.delete_at(i+1)
  3548.            i-=1 # revisit this text command
  3549.            changed=true
  3550.          elsif lines>=3 && list[i+lines] && list[i+lines].code==101
  3551.            # Check whether a sentence is being broken midway
  3552.            # between two Text commands
  3553.            lastLine=list[i+lines-1].parameters[0].sub(/\s+$/,"")
  3554.            if lastLine.length>0 && !lastLine[/[\\<]/] && lastLine[/[^\.,\!\?\;\-\"]$/]
  3555.             message=list[i].parameters[0]
  3556.             j=i+1; while j<list.length
  3557.              break if list[j].code!=401
  3558.              message+="\n"+list[j].parameters[0]
  3559.              j+=1
  3560.            end
  3561.            punct=[message.rindex(". "),message.rindex(".\n"),
  3562.               message.rindex("!"),message.rindex("?"),-1].compact.max
  3563.            if punct==-1
  3564.              punct=[message.rindex(", "),message.rindex(",\n"),-1].compact.max
  3565.            end
  3566.            if punct!=-1
  3567.              # Delete old message
  3568.              indent=list[i].indent
  3569.              newMessage=message[0,punct+1].split("\n")
  3570.              nextMessage=message[punct+1,message.length].sub(/^\s+/,"").split("\n")
  3571.              list[i+lines].code=401
  3572.              lines.times { list.delete_at(i) }
  3573.              j=nextMessage.length-1;while j>=0
  3574.                list.insert(i,RPG::EventCommand.new(
  3575.                j==0 ? 101 : 401,indent,[nextMessage[j]]))
  3576.              j-=1;end
  3577.              j=newMessage.length-1;while j>=0
  3578.                list.insert(i,RPG::EventCommand.new(
  3579.                j==0 ? 101 : 401,indent,[newMessage[j]]))
  3580.              j-=1;end
  3581.              changed=true
  3582.              i+=1
  3583.              next
  3584.            end
  3585.          end
  3586.        end
  3587.      elsif list[i].code==111 && list[i].parameters[0]==12
  3588.        x=[list[i].parameters[1]]
  3589.        changed|=pbChangeScripts(x)
  3590.        list[i].parameters[1]=x[0]
  3591.        script=x[0]
  3592.        if script[trainerMoneyRE]
  3593.          # Checking money directly
  3594.          operator=$1
  3595.          amount=$2.to_i
  3596.          params[0]=7
  3597.          if operator=="<"
  3598.            params[2]=1
  3599.            params[1]=amount-1
  3600.          elsif operator=="<="
  3601.            params[2]=1
  3602.            params[1]=amount
  3603.          elsif operator==">"
  3604.            params[2]=0
  3605.            params[1]=amount+1
  3606.          elsif operator==">="
  3607.            params[2]=0
  3608.            params[1]=amount
  3609.          end
  3610.          changed=true
  3611.        elsif script[itemBallRE] && i>0
  3612.          # Using pbItemBall on non-item events
  3613.          list[i].parameters[1]=script.sub(/pbItemBall/,"pbReceiveItem")
  3614.          changed=true
  3615.        elsif script[/^\s*(Kernel\.)?(pbTrainerBattle|pbDoubleTrainerBattle)/]
  3616.          # Empty trainer battle conditional branches
  3617.          j=i+1
  3618.          isempty=true
  3619.          elseIndex=-1
  3620.          # Check if page is empty
  3621.          while j<page.list.length
  3622.            if list[j].indent<=list[i].indent
  3623.              if list[j].code==411 # Else
  3624.                elseIndex=j
  3625.              else
  3626.                break
  3627.              end
  3628.            end
  3629.            if list[j].code!=0 && list[j].code!=411
  3630.              isempty=false
  3631.              break
  3632.            end
  3633.            j+=1
  3634.          end
  3635.          if isempty
  3636.            if elseIndex>=0
  3637.              list.insert(elseIndex+1,
  3638.                 RPG::EventCommand.new(115,list[i].indent+1,[]) # Exit Event Processing
  3639.              )
  3640.            else
  3641.              list.insert(i+1,
  3642.                 RPG::EventCommand.new(0,list[i].indent+1,[]), # Empty Event
  3643.                 RPG::EventCommand.new(411,list[i].indent,[]), # Else
  3644.                 RPG::EventCommand.new(115,list[i].indent+1,[]) # Exit Event Processing
  3645.              )
  3646.            end
  3647.            changed=true
  3648.          end
  3649.        end
  3650.      end
  3651.      i+=1
  3652.    end
  3653.  end
  3654.  return changed ? event : nil
  3655. end
  3656.  
  3657. def pbConvertToItemEvent(event)
  3658.  return nil if !event || event.pages.length==0
  3659.  ret=RPG::Event.new(event.x,event.y)
  3660.  name=event.name
  3661.  ret.name=event.name
  3662.  ret.id=event.id
  3663.  ret.pages=[]
  3664.  itemid=nil
  3665.  itemname=""
  3666.  hidden=false
  3667.  if name[/^HiddenItem\:\s*(\w+)\s*$/]
  3668.    itemname=$1
  3669.    return nil if !hasConst?(PBItems,itemname)
  3670.    itemid=PBItems.const_get(itemname)
  3671.    ret.name="HiddenItem"
  3672.    hidden=true
  3673.  elsif name[/^Item\:\s*(\w+)\s*$/]
  3674.    itemname=$1
  3675.    return nil if !hasConst?(PBItems,itemname)
  3676.    itemid=PBItems.const_get(itemname)
  3677.    ret.name="Item"
  3678.  else
  3679.    return nil
  3680.  end
  3681.  # Event page 1
  3682.  page=RPG::Event::Page.new
  3683.  if !hidden
  3684.    page.graphic.character_name="Object ball"
  3685.  end
  3686.  page.list=[]
  3687.  pbPushBranch(page.list,
  3688.     sprintf("Kernel.pbItemBall(PBItems:"+":%s)",itemname))
  3689.  pbPushSelfSwitch(page.list,"A",true,1)
  3690.  pbPushElse(page.list,1)
  3691.  pbPushBranchEnd(page.list,1)
  3692.  pbPushEnd(page.list)
  3693.  ret.pages.push(page)
  3694.  # Event page 2
  3695.  page=RPG::Event::Page.new
  3696.  page.condition.self_switch_valid=true
  3697.  page.condition.self_switch_ch="A"
  3698.  ret.pages.push(page)
  3699.  return ret
  3700. end
  3701.  
  3702. def pbStartsWith(s,pfx)
  3703.  return s[0,pfx.length]==pfx
  3704. end
  3705.  
  3706. def pbConvertToTrainerEvent(event,trainerChecker)
  3707.  return nil if !event || event.pages.length==0
  3708.  ret=RPG::Event.new(event.x,event.y)
  3709.  ret.name=event.name
  3710.  ret.id=event.id
  3711.  commands=[]
  3712.  list=event.pages[0].list
  3713.  return nil if list.length<2
  3714.  isFirstCommand=false
  3715.  i=0; while i<list.length
  3716.    if list[i].code==108
  3717.      command=list[i].parameters[0]
  3718.      j=i+1; while j<list.length
  3719.        break if list[j].code!=408
  3720.        command+="\r\n"+list[j].parameters[0]
  3721.        j+=1
  3722.      end
  3723.      if command[/^(Battle\:|Type\:|Name\:|EndSpeech\:|VanishIfSwitch\:|EndBattle\:|RegSpeech\:|BattleID\:|EndIfSwitch\:|DoubleBattle\:|Backdrop\:|Continue\:)/i]
  3724.        commands.push(command)
  3725.        isFirstCommand=true if i==0
  3726.      end
  3727.    end
  3728.    i+=1
  3729.  end
  3730.  return nil if commands.length==0
  3731.  if isFirstCommand && !event.name[/Trainer/]
  3732.    ret.name="Trainer(3)"
  3733.  elsif isFirstCommand && event.name[/^\s*Trainer\s+\((\d+)\)\s*$/]
  3734.    ret.name="Trainer(#{$1})"
  3735.   end
  3736.   firstpage=Marshal::load(Marshal.dump(event.pages[0]))
  3737.   firstpage.trigger=2
  3738.   firstpage.list=[]
  3739.   trtype=nil
  3740.   trname=nil
  3741.   battles=[]
  3742.   endbattles=[]
  3743.   realcommands=[]
  3744.   endspeeches=[]
  3745.   regspeech=nil
  3746.   backdrop=nil
  3747.   battleid=0
  3748.   endifswitch=[]
  3749.   vanishifswitch=[]
  3750.   doublebattle=false
  3751.   continue=false
  3752.   for command in commands
  3753.     if command[/^Battle\:\s*([\s\S]+)$/i]
  3754.       battles.push($~[1])
  3755.       pbPushComment(firstpage.list,command)
  3756.     end
  3757.     if command[/^Type\:\s*([\s\S]+)$/i]
  3758.       trtype=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3759.       pbPushComment(firstpage.list,command)
  3760.     end
  3761.     if command[/^Name\:\s*([\s\S]+)$/i]
  3762.       trname=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3763.       pbPushComment(firstpage.list,command)
  3764.     end
  3765.     if command[/^EndSpeech\:\s*([\s\S]+)$/i]
  3766.       endspeeches.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
  3767.       pbPushComment(firstpage.list,command)
  3768.     end
  3769.     if command[/^EndIfSwitch\:\s*([\s\S]+)$/i]
  3770.       endifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
  3771.       pbPushComment(firstpage.list,command)
  3772.     end
  3773.     if command[/^DoubleBattle\:\s*([\s\S]+)$/i]
  3774.       value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3775.       doublebattle=true if value.upcase=="TRUE" || value.upcase=="YES"
  3776.       pbPushComment(firstpage.list,command)
  3777.     end
  3778.     if command[/^VanishIfSwitch\:\s*([\s\S]+)$/i]
  3779.       vanishifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
  3780.       pbPushComment(firstpage.list,command)
  3781.     end
  3782.     if command[/^Backdrop\:\s*([\s\S]+)$/i]
  3783.       backdrop=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3784.       pbPushComment(firstpage.list,command)
  3785.     end
  3786.     if command[/^RegSpeech\:\s*([\s\S]+)$/i]
  3787.       regspeech=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3788.       pbPushComment(firstpage.list,command)
  3789.     end
  3790.     if command[/^EndBattle\:\s*([\s\S]+)$/i]
  3791.       endbattles.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
  3792.       pbPushComment(firstpage.list,command)
  3793.     end
  3794.     if command[/^BattleID\:\s*(\d+)$/i]
  3795.       battleid=$~[1].to_i
  3796.       pbPushComment(firstpage.list,command)
  3797.     end
  3798.     if command[/^Continue\:\s*([\s\S]+)$/i]
  3799.       value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3800.       continue=true if value.upcase=="TRUE" || value.upcase=="YES"
  3801.       pbPushComment(firstpage.list,command)
  3802.     end
  3803.   end
  3804.   if battles.length<=0
  3805.     return nil
  3806.   end
  3807.   if firstpage.graphic.character_name=="" && hasConst?(PBTrainers,trtype)
  3808.     trainerid=getConst(PBTrainers,trtype)
  3809.     if trainerid
  3810.       filename=pbTrainerCharNameFile(trainerid)
  3811.       if FileTest.image_exist?("Graphics/Characters/"+filename)
  3812.         firstpage.graphic.character_name=sprintf(filename)
  3813.       end
  3814.     end
  3815.   end
  3816.   safetrcombo=sprintf("PBTrainers:"+":%s,\"%s\"",trtype,safequote(trname))
  3817.   safetrcombo2=sprintf(":%s,\"%s\"",trtype,safequote(trname))
  3818.   introplay=sprintf("pbTrainerIntro(:%s)",trtype)
  3819.   pbPushScript(firstpage.list,introplay)
  3820.   pbPushScript(firstpage.list,"Kernel.pbNoticePlayer(get_character(0))")
  3821.   pbPushText(firstpage.list,battles[0])
  3822.   if battles.length>1
  3823.     pbPushScript(firstpage.list,sprintf("Kernel.pbTrainerCheck(%s,%d,%d)",safetrcombo2,battles.length,battleid))
  3824.   end
  3825.   if backdrop
  3826.     pbPushScript(firstpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)))
  3827.   end
  3828.   espeech=(endspeeches[0]) ? endspeeches[0] : "..."
  3829.   # Run trainer check now, except in editor
  3830.   trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid) if !$INEDITOR
  3831.   pbPushBranch(firstpage.list,
  3832.      sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s)",
  3833.      safetrcombo,safequote2(espeech),doublebattle ? "true" : "false",battleid,continue ? "true" : "false")
  3834.   )
  3835.   if battles.length>1
  3836.     pbPushScript(firstpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  3837.   end
  3838.   pbPushSelfSwitch(firstpage.list,"A",true,1)
  3839.   pbPushBranchEnd(firstpage.list,1)
  3840.   pbPushScript(firstpage.list,"pbTrainerEnd",0)
  3841.   pbPushEnd(firstpage.list)
  3842.   secondpage=Marshal::load(Marshal.dump(firstpage))
  3843.   secondpage.list=[]
  3844.   secondpage.trigger=0
  3845.   secondpage.condition=firstpage.condition.clone
  3846.   thirdpage=Marshal::load(Marshal.dump(secondpage))
  3847.   thirdpage.list=secondpage.list.clone
  3848.   thirdpage.condition=secondpage.condition.clone
  3849.   secondpage.condition.self_switch_valid=true
  3850.   secondpage.condition.self_switch_ch="A"
  3851.   thirdpage.condition.self_switch_valid=true
  3852.   thirdpage.condition.self_switch_ch="B"
  3853.   for i in 1...battles.length
  3854.     if endspeeches.length==0
  3855.       espeech="..."
  3856.     else
  3857.       espeech=(endspeeches[i]) ? endspeeches[i] : endspeeches[endspeeches.length-1]
  3858.     end
  3859.     if endbattles.length==0
  3860.       ebattle=nil
  3861.     else
  3862.       ebattle=(endbattles[i]) ? endbattles[i] : endbattles[endbattles.length-1]
  3863.     end
  3864.     if i==battles.length-1
  3865.       pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)>=%d",safetrcombo,i))
  3866.       pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)>=%d",safetrcombo,i))
  3867.     else
  3868.       pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
  3869.       pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
  3870.     end
  3871.     pbPushText(secondpage.list,ebattle,1)
  3872.     pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  3873.     pbPushExit(secondpage.list,1)
  3874.     pbPushBranchEnd(secondpage.list,1)
  3875.     pbPushScript(thirdpage.list,introplay,1)
  3876.     pbPushText(thirdpage.list,battles[i],1)
  3877.     # Run trainer check now, except in editor
  3878.     trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid+i) if !$INEDITOR
  3879.     if backdrop
  3880.       pbPushScript(thirdpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)),1)
  3881.     end
  3882.     pbPushBranch(thirdpage.list,
  3883.        sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s)",
  3884.        safetrcombo,safequote2(espeech),doublebattle ? "true" : "false",battleid+i,continue ? "true" : "false"),1
  3885.     )
  3886.     pbPushScript(thirdpage.list,
  3887.        sprintf("pbPhoneIncrement(%s,%d)",safetrcombo,battles.length),2)
  3888.     pbPushSelfSwitch(thirdpage.list,"A",true,2)
  3889.     pbPushSelfSwitch(thirdpage.list,"B",false,2)
  3890.     pbPushScript(thirdpage.list,"pbTrainerEnd",2)
  3891.     pbPushBranchEnd(thirdpage.list,2)
  3892.     pbPushExit(thirdpage.list,1)
  3893.     pbPushBranchEnd(thirdpage.list,1)
  3894.   end
  3895.   ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3896.   pbPushText(secondpage.list,ebattle)
  3897.   if battles.length>1
  3898.     pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  3899.   end
  3900.   pbPushEnd(secondpage.list)
  3901.   pbPushEnd(thirdpage.list)
  3902.   if battles.length==1
  3903.     ret.pages=[firstpage,secondpage]
  3904.   else
  3905.     ret.pages=[firstpage,thirdpage,secondpage]
  3906.   end
  3907.   for endswitch in endifswitch
  3908.     ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3909.     endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
  3910.     endIfSwitchPage.condition=secondpage.condition.clone
  3911.     if endIfSwitchPage.condition.switch1_valid
  3912.       endIfSwitchPage.condition.switch2_valid=true
  3913.       endIfSwitchPage.condition.switch2_id=endswitch
  3914.     else
  3915.       endIfSwitchPage.condition.switch1_valid=true
  3916.       endIfSwitchPage.condition.switch1_id=endswitch
  3917.     end
  3918.     endIfSwitchPage.condition.self_switch_valid=false
  3919.     endIfSwitchPage.list=[]
  3920.     pbPushText(endIfSwitchPage.list,ebattle)
  3921.     pbPushEnd(endIfSwitchPage.list)
  3922.     ret.pages.push(endIfSwitchPage)
  3923.   end
  3924.   for endswitch in vanishifswitch
  3925.     ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3926.     endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
  3927.     endIfSwitchPage.graphic.character_name="" # make blank
  3928.     endIfSwitchPage.condition=secondpage.condition.clone
  3929.     if endIfSwitchPage.condition.switch1_valid
  3930.       endIfSwitchPage.condition.switch2_valid=true
  3931.       endIfSwitchPage.condition.switch2_id=endswitch
  3932.     else
  3933.       endIfSwitchPage.condition.switch1_valid=true
  3934.       endIfSwitchPage.condition.switch1_id=endswitch
  3935.     end
  3936.     endIfSwitchPage.condition.self_switch_valid=false
  3937.     endIfSwitchPage.list=[]
  3938.     pbPushEnd(endIfSwitchPage.list)
  3939.     ret.pages.push(endIfSwitchPage)
  3940.   end
  3941.   return ret
  3942. end
  3943.  
  3944. def pbCompileAnimations
  3945.   begin
  3946.     if $RPGVX
  3947.       pbanims=load_data("Data/PkmnAnimations.rvdata")
  3948.     else
  3949.       pbanims=load_data("Data/PkmnAnimations.rxdata")
  3950.     end
  3951.   rescue
  3952.     pbanims=PBAnimations.new
  3953.   end
  3954.   move2anim=[[],[]]
  3955. =begin
  3956.   if $RPGVX
  3957.     anims=load_data("Data/Animations.rvdata")
  3958.   else
  3959.     anims=load_data("Data/Animations.rxdata")
  3960.   end
  3961.   for anim in anims
  3962.     next if !anim || anim.frames.length==1
  3963.     found=false
  3964.     for i in 0...pbanims.length
  3965.       if pbanims[i] && pbanims[i].id==anim.id
  3966.         found=true if pbanims[i].array.length>1
  3967.         break
  3968.       end
  3969.     end
  3970.     if !found
  3971.       pbanims[anim.id]=pbConvertRPGAnimation(anim)
  3972.     end
  3973.   end
  3974. =end
  3975.   for i in 0...pbanims.length
  3976.     next if !pbanims[i]
  3977.     if pbanims[i].name[/^OppMove\:\s*(.*)$/]
  3978.       if Kernel.hasConst?(PBMoves,$~[1])
  3979.         moveid=PBMoves.const_get($~[1])
  3980.         move2anim[1][moveid]=i
  3981.       end
  3982.     elsif pbanims[i].name[/^Move\:\s*(.*)$/]
  3983.       if Kernel.hasConst?(PBMoves,$~[1])
  3984.         moveid=PBMoves.const_get($~[1])
  3985.         move2anim[0][moveid]=i
  3986.       end
  3987.     end
  3988.   end
  3989.   save_data(move2anim,"Data/move2anim.dat")
  3990.   save_data(pbanims,"Data/PkmnAnimations.rxdata")
  3991. end
  3992.  
  3993. def pbCompileAllData(mustcompile)
  3994.   FileLineData.clear
  3995.   if mustcompile
  3996.     if (!$INEDITOR || LANGUAGES.length<2) && pbRgssExists?("Data/messages.dat")
  3997.       MessageTypes.loadMessageFile("Data/messages.dat")
  3998.     end
  3999.     # No dependencies
  4000.     yield(_INTL("Compiling type data"))
  4001.     pbCompileTypes
  4002.     # No dependencies
  4003.     yield(_INTL("Compiling town map data"))
  4004.     pbCompileTownMap
  4005.     # No dependencies
  4006.     yield(_INTL("Compiling map connection data"))
  4007.     pbCompileConnections
  4008.     # No dependencies  
  4009.     yield(_INTL("Compiling ability data"))
  4010.     pbCompileAbilities
  4011.     # Depends on PBTypes
  4012.     yield(_INTL("Compiling move data"))
  4013.     pbCompileMoves
  4014.     # Depends on PBMoves
  4015.     yield(_INTL("Compiling item data"))
  4016.     pbCompileItems
  4017.     # Depends on PBMoves, PBItems, PBTypes, PBAbilities
  4018.     yield(_INTL("Compiling Pokemon data"))
  4019.     pbCompilePokemonData
  4020.     # Depends on PBSpecies, PBMoves
  4021.     yield(_INTL("Compiling machine data"))
  4022.     pbCompileMachines
  4023.     # Depends on PBSpecies, PBItems, PBMoves
  4024.     yield(_INTL("Compiling Trainer data"))
  4025.     pbCompileTrainers
  4026.     # Depends on PBTrainers
  4027.     yield(_INTL("Compiling phone data"))
  4028.     pbCompilePhoneData
  4029.     # Depends on PBTrainers
  4030.     yield(_INTL("Compiling metadata"))
  4031.     pbCompileMetadata
  4032.     # Depends on PBTrainers
  4033.     yield(_INTL("Compiling battle Trainer data"))
  4034.     pbCompileTrainerLists
  4035.     # Depends on PBSpecies
  4036.     yield(_INTL("Compiling encounter data"))
  4037.     pbCompileEncounters
  4038.     # Depends on PBSpecies, PBMoves
  4039.     yield(_INTL("Compiling shadow move data"))
  4040.     pbCompileShadowMoves
  4041.     #Depends on PBContestMoves
  4042.     yield(_INTL("Compiling contest moves"))
  4043.     pbCompileContestMoves
  4044.     yield(_INTL("Compiling messages"))
  4045.   else
  4046.     if (!$INEDITOR || LANGUAGES.length<2) && safeExists?("Data/messages.dat")
  4047.       MessageTypes.loadMessageFile("Data/messages.dat")
  4048.     end
  4049.   end
  4050.   pbCompileAnimations
  4051.   pbCompileTrainerEvents(mustcompile)
  4052.   pbSetTextMessages
  4053.   MessageTypes.saveMessages
  4054.   if !$INEDITOR && LANGUAGES.length>=2
  4055.     pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
  4056.   end
  4057. end
  4058.  
  4059. def pbImportNewMaps
  4060.   return false if !$DEBUG
  4061.   mapfiles={}
  4062.   # Get IDs of all maps in the Data folder
  4063.   Dir.chdir("Data"){
  4064.      mapdata=sprintf("Map*.%s","rxdata",$RPGVX ? "rvdata" : "rxdata")
  4065.      for map in Dir.glob(mapdata)
  4066.        if map[/map(\d+)\.rxdata/i]
  4067.          mapfiles[$1.to_i(10)]=true
  4068.        end
  4069.      end
  4070.   }
  4071.   mapinfos=pbLoadRxData("Data/MapInfos")
  4072.   maxOrder=0
  4073.   # Exclude maps found in mapinfos
  4074.   for id in mapinfos.keys
  4075.     next if !mapinfos.id
  4076.     if mapfiles[id]
  4077.       mapfiles.delete(id)
  4078.     end
  4079.     maxOrder=[maxOrder,mapinfos[id].order].max
  4080.   end
  4081.   # Import maps not found in mapinfos
  4082.   maxOrder+=1
  4083.   imported=false
  4084.   for id in mapfiles.keys
  4085.     next if id==999 # Ignore 999 (random dungeon map)
  4086.     mapname=sprintf("MAP%03d",id)
  4087.     mapinfo=RPG::MapInfo.new
  4088.     mapinfo.order=maxOrder
  4089.     maxOrder+=1
  4090.     mapinfo.name=mapname
  4091.     mapinfos[id]=mapinfo
  4092.     imported=true
  4093.   end
  4094.   if imported
  4095.     if $RPGVX
  4096.       save_data(mapinfos,"Data/MapInfos.rvdata")
  4097.     else
  4098.       save_data(mapinfos,"Data/MapInfos.rxdata")
  4099.     end
  4100.     Kernel.pbMessage(_INTL("New maps copied to the Data folder were successfully imported.",id))
  4101.   end
  4102.   return imported
  4103. end
  4104.  
  4105. if $DEBUG
  4106.   latestdatatime=0
  4107.   latesttexttime=0
  4108.   mustcompile=false
  4109.   mustcompile|=pbImportNewMaps
  4110.   mustcompile|=!(PBSpecies.respond_to?("maxValue") rescue false)
  4111.   if !safeIsDirectory?("PBS")
  4112.     Dir.mkdir("PBS") rescue nil
  4113.     pbSaveAllData()
  4114.     mustcompile=true
  4115.   end
  4116.   for i in 0...datafiles.length
  4117.     begin
  4118.       File.open("Data/#{datafiles[i]}"){|file|
  4119.          latestdatatime=[latestdatatime,file.mtime.to_i].max
  4120.       }
  4121.     rescue SystemCallError
  4122.       mustcompile=true
  4123.     end
  4124.   end
  4125.   for i in 0...textfiles.length
  4126.     begin
  4127.       File.open("PBS/#{textfiles[i]}"){|file|
  4128.         latesttexttime=[latesttexttime,file.mtime.to_i].max
  4129.       }
  4130.     rescue SystemCallError
  4131.     end
  4132.   end
  4133.   mustcompile=mustcompile || (latesttexttime>=latestdatatime)
  4134.   Input.update
  4135.   if Input.press?(Input::CTRL)
  4136.     mustcompile=true
  4137.   end
  4138.   if mustcompile
  4139.     for i in 0...datafiles.length
  4140.       begin
  4141.         File.delete("Data/#{datafiles[i]}")
  4142.         rescue SystemCallError
  4143.       end
  4144.     end
  4145.   end
  4146.   pbCompileAllData(mustcompile){|msg| Win32API.SetWindowText(msg) }
  4147. end
  4148.  
  4149.  
  4150.  
  4151. rescue Exception
  4152. e=$!
  4153. if "#{e.class}"=="Reset" || e.is_a?(Reset) || e.is_a?(SystemExit)
  4154.   raise e
  4155. end
  4156. pbPrintException(e)
  4157. for i in 0...datafiles.length
  4158.   begin
  4159.     File.delete("Data/#{datafiles[i]}")
  4160.   rescue SystemCallError
  4161.   end
  4162. end
  4163. if e.is_a?(Hangup)
  4164.   raise Reset.new
  4165. end
  4166. loop do
  4167.   Graphics.update
  4168. end
  4169. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement