Advertisement
Guest User

Untitled

a guest
Feb 7th, 2016
301
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 125.88 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.   itempluralnames=[]
  815.   itemdescs=[]
  816.   maxValue=0
  817.   pbCompilerEachCommentedLine("PBS/items.txt"){|line,lineno|
  818.      linerecord=pbGetCsvRecord(line,lineno,[0,"vnssuusuuUN"])
  819.      record=SerialRecord.new
  820.      record[ITEMID]        = linerecord[0]
  821.      constant=linerecord[1]
  822.      constants+="#{constant}=#{record[0]}\r\n"
  823.      record[ITEMNAME]      = linerecord[2]
  824.      itemnames[record[0]]=linerecord[2]
  825.      record[ITEMPLURAL]    = linerecord[3]
  826.      itempluralnames[record[0]]=linerecord[3]
  827.      record[ITEMPOCKET]    = linerecord[4]
  828.      record[ITEMPRICE]     = linerecord[5]
  829.      record[ITEMDESC]      = linerecord[6]
  830.      itemdescs[record[0]]=linerecord[6]
  831.      record[ITEMUSE]       = linerecord[7]
  832.      record[ITEMBATTLEUSE] = linerecord[8]
  833.      record[ITEMTYPE]      = linerecord[9]
  834.      if linerecord[9]!="" && linerecord[10]
  835.        record[ITEMMACHINE] = parseMove(linerecord[10])
  836.      else
  837.        record[ITEMMACHINE] = 0
  838.      end
  839.      maxValue=[maxValue,record[0]].max
  840.      records.push(record)
  841.   }
  842.   MessageTypes.setMessages(MessageTypes::Items,itemnames)
  843.   MessageTypes.setMessages(MessageTypes::ItemPlurals,itempluralnames)
  844.   MessageTypes.setMessages(MessageTypes::ItemDescriptions,itemdescs)
  845.   writeSerialRecords("Data/items.dat",records)
  846.   code="class PBItems\r\n#{constants}"
  847.   code+="\r\ndef PBItems.getName(id)\r\nreturn pbGetMessage(MessageTypes::Items,id)\r\nend\r\n"
  848.   code+="\r\ndef PBItems.getNamePlural(id)\r\nreturn pbGetMessage(MessageTypes::ItemPlurals,id)\r\nend\r\n"
  849.   code+="\r\ndef PBItems.getCount\r\nreturn #{records.length}\r\nend\r\n"
  850.   code+="\r\ndef PBItems.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  851.   eval(code)
  852.   pbAddScript(code,"PBItems")
  853.   Graphics.update
  854. end
  855.  
  856. def pbCompileConnections
  857.   records=[]
  858.   constants=""
  859.   itemnames=[]
  860.   pbCompilerEachPreppedLine("PBS/connections.txt"){|line,lineno|
  861.      hashenum={
  862.         "N"=>"N","North"=>"N",
  863.         "E"=>"E","East"=>"E",
  864.         "S"=>"S","South"=>"S",
  865.         "W"=>"W","West"=>"W"
  866.      }
  867.      record=[]
  868.      thisline=line.dup
  869.      record.push(csvInt!(thisline,lineno))
  870.      record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
  871.      record.push(csvInt!(thisline,lineno))
  872.      record.push(csvInt!(thisline,lineno))
  873.      record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
  874.      record.push(csvInt!(thisline,lineno))          
  875.      if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[0])) &&
  876.         !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[0]))
  877.        print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[0],FileLineData.linereport)
  878.      end
  879.      if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[3])) &&
  880.         !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[3]))
  881.        print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[3],FileLineData.linereport)
  882.      end
  883.      case record[1]
  884.      when "N"
  885.        raise _INTL("North side of first map must connect with south side of second map\r\n{1}",FileLineData.linereport) if record[4]!="S"
  886.      when "S"
  887.        raise _INTL("South side of first map must connect with north side of second map\r\n{1}",FileLineData.linereport) if record[4]!="N"
  888.      when "E"
  889.        raise _INTL("East side of first map must connect with west side of second map\r\n{1}",FileLineData.linereport) if record[4]!="W"
  890.      when "W"
  891.        raise _INTL("West side of first map must connect with east side of second map\r\n{1}",FileLineData.linereport) if record[4]!="E"
  892.      end
  893.      records.push(record)
  894.   }
  895.   save_data(records,"Data/connections.dat")
  896.   Graphics.update
  897. end
  898.  
  899. def strsplit(str,re)
  900.   ret=[]
  901.   tstr=str
  902.   while re=~tstr
  903.     ret[ret.length]=$~.pre_match
  904.     tstr=$~.post_match
  905.   end
  906.   ret[ret.length]=tstr if ret.length
  907.   return ret
  908. end
  909.  
  910. def canonicalize(c)
  911.   csplit=strsplit(c,/[\/\\]/)
  912.   pos=-1
  913.   ret=[]
  914.   retstr=""
  915.   for x in csplit
  916.     if x=="."
  917.     elsif x==".."
  918.       ret.delete_at(pos) if pos>=0
  919.       pos-=1
  920.     else
  921.       ret.push(x)
  922.       pos+=1
  923.     end
  924.   end
  925.   for i in 0...ret.length
  926.     retstr+="/" if i>0
  927.     retstr+=ret[i]
  928.   end
  929.   return retstr
  930. end
  931.  
  932. def pbGetConst(mod,item,err)
  933.   isdef=false
  934.   begin
  935.     isdef=mod.const_defined?(item.to_sym)
  936.   rescue
  937.     raise sprintf(err,item)
  938.   end
  939.   raise sprintf(err,item) if !isdef
  940.   return mod.const_get(item.to_sym)
  941. end
  942.  
  943. def parseItem(item)
  944.   clonitem=item.upcase
  945.   clonitem.sub!(/^\s*/){}
  946.   clonitem.sub!(/\s*$/){}
  947.   return pbGetConst(PBItems,clonitem,
  948.      _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}",
  949.      FileLineData.linereport))
  950. end
  951.  
  952. def parseSpecies(item)
  953.   clonitem=item.upcase
  954.   clonitem.gsub!(/^[\s\n]*/){}
  955.   clonitem.gsub!(/[\s\n]*$/){}
  956.   clonitem="NIDORANmA" if clonitem=="NIDORANMA"
  957.   clonitem="NIDORANfE" if clonitem=="NIDORANFE"
  958.   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))
  959. end
  960.  
  961. def parseMove(item)
  962.   clonitem=item.upcase
  963.   clonitem.sub!(/^\s*/){}
  964.   clonitem.sub!(/\s*$/){}
  965.   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))
  966. end
  967.  
  968. def parseNature(item)
  969.   clonitem=item.upcase
  970.   clonitem.sub!(/^\s*/){}
  971.   clonitem.sub!(/\s*$/){}
  972.   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))
  973. end
  974.  
  975. def parseTrainer(item)
  976.   clonitem=item.clone
  977.   clonitem.sub!(/^\s*/){}
  978.   clonitem.sub!(/\s*$/){}
  979.   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))
  980. end
  981.  
  982. def pbFindScript(a,name)
  983.   a.each{|i|
  984.      next if !i
  985.      return i if i[1]==name
  986.   }
  987.   return nil
  988. end
  989.  
  990. def pbAddScript(script,sectionname)
  991.   begin
  992.     scripts=load_data("Data/Constants.rxdata")
  993.     scripts=[] if !scripts
  994.   rescue
  995.     scripts=[]
  996.   end
  997.   s=pbFindScript(scripts,sectionname)
  998.   if s
  999.     s[2]=Zlib::Deflate.deflate("#{script}\r\n")
  1000.   else
  1001.     scripts.push([rand(100000000),sectionname,Zlib::Deflate.deflate("#{script}\r\n")])
  1002.   end
  1003.   save_data(scripts,"Data/Constants.rxdata")
  1004. end
  1005.  
  1006. def pbCompileEncounters
  1007.   lines=[]
  1008.   linenos=[]
  1009.   FileLineData.file="PBS/encounters.txt"
  1010.   File.open("PBS/encounters.txt","rb"){|f|
  1011.      lineno=1
  1012.      f.each_line {|line|
  1013.         if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  1014.           line=line[3,line.length-3]
  1015.         end
  1016.         line=prepline(line)
  1017.         if line.length!=0
  1018.           lines[lines.length]=line
  1019.           linenos[linenos.length]=lineno
  1020.         end
  1021.         lineno+=1
  1022.      }
  1023.   }
  1024.   encounters={}
  1025.   thisenc=nil
  1026.   lastenc=-1
  1027.   lastenclen=0
  1028.   needdensity=false
  1029.   lastmapid=-1
  1030.   i=0;
  1031.   while i<lines.length
  1032.     line=lines[i]
  1033.     FileLineData.setLine(line,linenos[i])
  1034.     mapid=line[/^\d+$/]
  1035.     if mapid
  1036.       lastmapid=mapid
  1037.       if thisenc && (thisenc[1][EncounterTypes::Land] ||
  1038.                      thisenc[1][EncounterTypes::LandMorning] ||
  1039.                      thisenc[1][EncounterTypes::LandDay] ||
  1040.                      thisenc[1][EncounterTypes::BugContest] ||
  1041.                      thisenc[1][EncounterTypes::LandNight]) &&
  1042.                      thisenc[1][EncounterTypes::Cave]
  1043.         raise _INTL("Can't define both Land and Cave encounters in the same area (map ID {1})",mapid)
  1044.       end
  1045.       thisenc=[EncounterTypes::EnctypeDensities.clone,[]]
  1046.       encounters[mapid.to_i]=thisenc
  1047.       needdensity=true
  1048.       i+=1
  1049.       next
  1050.     end
  1051.     enc=findIndex(EncounterTypes::Names){|val| val==line}
  1052.     if enc>=0
  1053.       needdensity=false
  1054.       enclines=EncounterTypes::EnctypeChances[enc].length
  1055.       encarray=[]
  1056.       j=i+1; k=0
  1057.       while j<lines.length && k<enclines
  1058.         line=lines[j]
  1059.         FileLineData.setLine(lines[j],linenos[j])
  1060.         splitarr=strsplit(line,/\s*,\s*/)
  1061.         if !splitarr || splitarr.length<2
  1062.           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}",
  1063.              line,lastmapid,FileLineData.linereport)
  1064.         end
  1065.         splitarr[2]=splitarr[1] if splitarr.length==2
  1066.         splitarr[1]=splitarr[1].to_i
  1067.         splitarr[2]=splitarr[2].to_i
  1068.         maxlevel=PBExperience::MAXLEVEL
  1069.         if splitarr[1]<=0 || splitarr[1]>maxlevel
  1070.           raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[1],FileLineData.linereport)
  1071.         end
  1072.         if splitarr[2]<=0 || splitarr[2]>maxlevel
  1073.           raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[2],FileLineData.linereport)
  1074.         end
  1075.         if splitarr[1]>splitarr[2]
  1076.           raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}",line,FileLineData.linereport)
  1077.         end
  1078.         splitarr[0]=parseSpecies(splitarr[0])
  1079.         linearr=splitarr
  1080.         encarray.push(linearr)
  1081.         thisenc[1][enc]=encarray
  1082.         j+=1
  1083.         k+=1
  1084.       end
  1085.       if j==lines.length && k<enclines
  1086.          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}",
  1087.             enclines,lastmapid,FileLineData.linereport)
  1088.       end
  1089.       i=j
  1090.     elsif needdensity
  1091.       needdensity=false
  1092.       nums=strsplit(line,/,/)
  1093.       if nums && nums.length>=3
  1094.         for j in 0...EncounterTypes::EnctypeChances.length
  1095.           next if !EncounterTypes::EnctypeChances[j] ||
  1096.                   EncounterTypes::EnctypeChances[j].length==0
  1097.           next if EncounterTypes::EnctypeCompileDens[j]==0
  1098.           thisenc[0][j]=nums[EncounterTypes::EnctypeCompileDens[j]-1].to_i
  1099.         end
  1100.       else
  1101.         raise _INTL("Wrong syntax for densities in encounters.txt; got \"{1}\"\r\n{2}",line,FileLineData.linereport)
  1102.       end
  1103.       i+=1
  1104.     else
  1105.       raise _INTL("Undefined encounter type {1}, expected one of the following:\r\n{2}\r\n{3}",
  1106.          line,EncounterTypes::Names.inspect,FileLineData.linereport)
  1107.     end
  1108.   end
  1109.   save_data(encounters,"Data/encounters.dat")
  1110. end
  1111.  
  1112. def pbCheckByte(x,valuename)
  1113.   if x<0 || x>255
  1114.     raise _INTL("The value \"{1}\" must be from 0 through 255 (0x00-0xFF in hex), got a value of {2}\r\n{3}",
  1115.        valuename,x,FileLineData.linereport)
  1116.   end
  1117. end
  1118.  
  1119. def pbCheckWord(x,valuename)
  1120.   if x<0 || x>65535
  1121.     raise _INTL("The value \"{1}\" must be from 0 through 65535 (0x0000-0xFFFF in hex), got a value of {2}\r\n{3}",
  1122.        valuename,x,FileLineData.linereport)
  1123.   end
  1124. end
  1125.  
  1126. def pbCheckSignedWord(x,valuename)
  1127.   if x<-32768 || x>32767
  1128.     raise _INTL("The value \"{1}\" must be from -32768 through 32767, got a value of {2}\r\n{3}",
  1129.        valuename,x,FileLineData.linereport)
  1130.   end
  1131. end
  1132.  
  1133. def pbCheckSignedByte(x,valuename)
  1134.   if x<-128 || x>127
  1135.     raise _INTL("The value \"{1}\" must be from -128 through 127, got a value of {2}\r\n{3}",
  1136.        valuename,x,FileLineData.linereport)
  1137.   end
  1138. end
  1139.  
  1140.  
  1141.  
  1142. class PBMoveDataOld
  1143.   attr_reader :function,:basedamage,:type,:accuracy
  1144.   attr_reader :totalpp,:addlEffect,:target,:priority
  1145.   attr_reader :flags
  1146.   attr_reader :category#,:contestType
  1147.  
  1148.   def initialize(moveid)
  1149.     movedata=pbRgssOpen("Data/rsattacks.dat")
  1150.     movedata.pos=moveid*9
  1151.     @function=movedata.fgetb
  1152.     @basedamage=movedata.fgetb
  1153.     @type=movedata.fgetb
  1154.     @accuracy=movedata.fgetb
  1155.     @totalpp=movedata.fgetb
  1156.     @addlEffect=movedata.fgetb
  1157.     @target=movedata.fgetb
  1158.     @priority=movedata.fgetsb
  1159.     @flags=movedata.fgetb
  1160.     movedata.close
  1161.   end
  1162.  
  1163.   def category
  1164.     return 2 if @basedamage==0
  1165.     return @type<10 ? 0 : 1
  1166.   end
  1167. end
  1168.  
  1169.  
  1170.  
  1171. def pbCompileMoves
  1172.   records=[]
  1173.   movenames=[]
  1174.   movedescs=[]
  1175.   movedata=[]
  1176.   maxValue=0
  1177.   haveRsAttacks=pbRgssExists?("Data/rsattacks.dat")
  1178.   pbCompilerEachPreppedLine("PBS/moves.txt"){|line,lineno|
  1179.      thisline=line.clone
  1180.      record=[]
  1181.      flags=0
  1182.      begin
  1183.        record=pbGetCsvRecord(line,lineno,[0,"vnsxueeuuuxiss",
  1184.           nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"],
  1185.           nil,nil,nil,nil,nil,nil,nil
  1186.        ])
  1187.        pbCheckWord(record[3],_INTL("Function code"))
  1188.        flags|=1 if record[12][/a/]
  1189.        flags|=2 if record[12][/b/]
  1190.        flags|=4 if record[12][/c/]
  1191.        flags|=8 if record[12][/d/]
  1192.        flags|=16 if record[12][/e/]
  1193.        flags|=32 if record[12][/f/]
  1194.        flags|=64 if record[12][/g/]
  1195.        flags|=128 if record[12][/h/]
  1196.        flags|=256 if record[12][/i/]
  1197.        flags|=512 if record[12][/j/]
  1198.        flags|=1024 if record[12][/k/]
  1199.        flags|=2048 if record[12][/l/]
  1200.        flags|=4096 if record[12][/m/]
  1201.        flags|=8192 if record[12][/n/]
  1202.        flags|=16384 if record[12][/o/]
  1203.        flags|=32768 if record[12][/p/]
  1204.      rescue
  1205.        oldmessage=$!.message
  1206.        raise if !haveRsAttacks
  1207.        begin
  1208.          oldrecord=pbGetCsvRecord(thisline,lineno,[0,"unss",nil,nil,nil,nil])
  1209.        rescue
  1210.          raise $!.message+"\r\n"+oldmessage
  1211.        end
  1212.        oldmovedata=PBMoveDataOld.new(oldrecord[0])
  1213.        flags=oldmovedata.flags
  1214.        record=[oldrecord[0],oldrecord[1],oldrecord[2],
  1215.           oldmovedata.function,
  1216.           oldmovedata.basedamage,
  1217.           oldmovedata.type,
  1218.           oldmovedata.category,
  1219.           oldmovedata.accuracy,
  1220.           oldmovedata.totalpp,
  1221.           oldmovedata.addlEffect,
  1222.           oldmovedata.target,
  1223.           oldmovedata.priority,
  1224.           oldmovedata.flags,
  1225.           0, # No contest type defined
  1226.           oldrecord[3]]
  1227.      end
  1228.      pbCheckWord(record[3],_INTL("Function code"))
  1229.      pbCheckByte(record[4],_INTL("Base damage"))
  1230.      if record[6]==2 && record[4]!=0
  1231.        raise _INTL("Status moves must have a base damage of 0, use either Physical or Special\r\n{1}",FileLineData.linereport)
  1232.      end
  1233.      if record[6]!=2 && record[4]==0
  1234.        print _INTL(
  1235.           "Warning: Physical and special moves can't have a base damage of 0, changing to a Status move\r\n{1}",FileLineData.linereport)
  1236.        record[6]=2
  1237.      end
  1238.      pbCheckByte(record[7],_INTL("Accuracy"))
  1239.      pbCheckByte(record[8],_INTL("Total PP"))
  1240.      pbCheckByte(record[9],_INTL("Additional Effect"))
  1241.      pbCheckWord(record[10],_INTL("Target"))
  1242.      pbCheckSignedByte(record[11],_INTL("Priority"))
  1243.      maxValue=[maxValue,record[0]].max
  1244.      movedata[record[0]]=[
  1245.         record[3],  # Function code
  1246.         record[4],  # Damage
  1247.         record[5],  # Type
  1248.         record[6],  # Category
  1249.         record[7],  # Accuracy
  1250.         record[8],  # Total PP
  1251.         record[9],  # Effect chance
  1252.         record[10], # Target
  1253.         record[11], # Priority
  1254.         flags,      # Flags
  1255.         0           # Dummy value, used to be contest type
  1256.      ].pack("vCCCCCCvCvC")
  1257.      movenames[record[0]]=record[2]  # Name
  1258.      movedescs[record[0]]=record[13] # Description
  1259.      records.push(record)
  1260.   }
  1261.   defaultdata=[0,0,0,0,0,0,0,0,0,0,0].pack("vCCCCCCvCvC")
  1262.   File.open("Data/moves.dat","wb"){|file|
  1263.      for i in 0...movedata.length
  1264.        file.write(movedata[i] ? movedata[i] : defaultdata)
  1265.      end
  1266.   }
  1267.   MessageTypes.setMessages(MessageTypes::Moves,movenames)
  1268.   MessageTypes.setMessages(MessageTypes::MoveDescriptions,movedescs)
  1269.   code="class PBMoves\r\n"
  1270.   for rec in records
  1271.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1272.   end
  1273.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::Moves,id)\r\nend"
  1274.   code+="\r\ndef self.getCount\r\nreturn #{records.length}\r\nend"
  1275.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1276.   eval(code)
  1277.   pbAddScript(code,"PBMoves")
  1278. end
  1279.  
  1280. def pbCompileAbilities
  1281.   records=[]
  1282.   movenames=[]
  1283.   movedescs=[]
  1284.   maxValue=0
  1285.   pbCompilerEachPreppedLine("PBS/abilities.txt"){|line,lineno|
  1286.      record=pbGetCsvRecord(line,lineno,[0,"vnss"])
  1287.      movenames[record[0]]=record[2]
  1288.      movedescs[record[0]]=record[3]
  1289.      maxValue=[maxValue,record[0]].max
  1290.      records.push(record)
  1291.   }
  1292.   MessageTypes.setMessages(MessageTypes::Abilities,movenames)
  1293.   MessageTypes.setMessages(MessageTypes::AbilityDescs,movedescs)
  1294.   code="class PBAbilities\r\n"
  1295.   for rec in records
  1296.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1297.   end
  1298.   code+="\r\ndef PBAbilities.getName(id)\r\nreturn pbGetMessage(MessageTypes::Abilities,id)\r\nend"
  1299.   code+="\r\ndef PBAbilities.getCount\r\nreturn #{records.length}\r\nend\r\n"
  1300.   code+="\r\ndef PBAbilities.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1301.   eval(code)
  1302.   pbAddScript(code,"PBAbilities")
  1303. end
  1304.  
  1305. def pbExtractTrainers
  1306.   trainertypes=nil
  1307.   pbRgssOpen("Data/trainertypes.dat","rb"){|f|
  1308.      trainertypes=Marshal.load(f)
  1309.   }
  1310.   return if !trainertypes
  1311.   File.open("trainertypes.txt","wb"){|f|
  1312.      f.write(0xEF.chr)
  1313.      f.write(0xBB.chr)
  1314.      f.write(0xBF.chr)
  1315.      for i in 0...trainertypes.length
  1316.        next if !trainertypes[i]
  1317.        record=trainertypes[i]
  1318.        begin
  1319.          cnst=getConstantName(PBTrainers,record[0])
  1320.        rescue
  1321.          next
  1322.        end
  1323.        f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s\r\n",
  1324.           record[0],csvquote(cnst),csvquote(record[2]),
  1325.           record[3],csvquote(record[4]),csvquote(record[5]),csvquote(record[6]),
  1326.           record[7] ? ["Male","Female","Mixed"][record[7]] : "Mixed"
  1327.        ))
  1328.      end
  1329.   }
  1330. end
  1331.  
  1332. def pbCompileTrainers
  1333.   # Trainer types
  1334.   records=[]
  1335.   trainernames=[]
  1336.   count=0
  1337.   maxValue=0
  1338.   pbCompilerEachPreppedLine("PBS/trainertypes.txt"){|line,lineno|
  1339.      record=pbGetCsvRecord(line,lineno,[0,"unsUSSSeU", # ID can be 0
  1340.         nil,nil,nil,nil,nil,nil,nil,{
  1341.         ""=>2,"Male"=>0,"M"=>0,"0"=>0,"Female"=>1,"F"=>1,"1"=>1,"Mixed"=>2,"X"=>2,"2"=>2
  1342.         },nil]
  1343.      )
  1344.      if record[3] && (record[3]<0 || record[3]>255)
  1345.        raise _INTL("Bad money amount (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
  1346.      end
  1347.      record[3]=30 if !record[3]
  1348.      if record[8] && (record[8]<0 || record[8]>255)
  1349.        raise _INTL("Bad skill value (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
  1350.      end
  1351.      record[8]=record[3] if !record[8]
  1352.      trainernames[record[0]]=record[2]
  1353.      if records[record[0]]
  1354.        raise _INTL("Two trainer types ({1} and {2}) have the same ID ({3}), which is not allowed.\r\n{4}",
  1355.           records[record[0]][1],record[1],record[0],FileLineData.linereport)
  1356.      end
  1357.      records[record[0]]=record
  1358.      maxValue=[maxValue,record[0]].max
  1359.   }
  1360.   count=records.compact.length
  1361.   MessageTypes.setMessages(MessageTypes::TrainerTypes,trainernames)
  1362.   code="class PBTrainers\r\n"
  1363.   for rec in records
  1364.     next if !rec
  1365.     code+="#{rec[1]}=#{rec[0]}\r\n"
  1366.   end
  1367.   code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::TrainerTypes,id)\r\nend"
  1368.   code+="\r\ndef self.getCount\r\nreturn #{count}\r\nend"
  1369.   code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  1370.   eval(code)
  1371.   pbAddScript(code,"PBTrainers")
  1372.   File.open("Data/trainertypes.dat","wb"){|f|
  1373.      Marshal.dump(records,f)
  1374.   }
  1375.   # Individual trainers
  1376.   lines=[]
  1377.   linenos=[]
  1378.   lineno=1
  1379.   File.open("PBS/trainers.txt","rb"){|f|
  1380.      FileLineData.file="PBS/trainers.txt"
  1381.      f.each_line {|line|
  1382.         if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
  1383.           line=line[3,line.length-3]
  1384.         end
  1385.         line=prepline(line)
  1386.         if line!=""
  1387.           lines.push(line)
  1388.           linenos.push(lineno)
  1389.         end
  1390.         lineno+=1
  1391.      }
  1392.   }
  1393.   nameoffset=0
  1394.   trainers=[]
  1395.   trainernames.clear
  1396.   i=0; loop do break unless i<lines.length
  1397.     FileLineData.setLine(lines[i],linenos[i])
  1398.     trainername=parseTrainer(lines[i])
  1399.     FileLineData.setLine(lines[i+1],linenos[i+1])
  1400.     nameline=strsplit(lines[i+1],/\s*,\s*/)
  1401.     name=nameline[0]
  1402.     raise _INTL("Trainer name too long\r\n{1}",FileLineData.linereport) if name.length>=0x10000
  1403.     trainernames.push(name)
  1404.     partyid=0
  1405.     if nameline[1] && nameline[1]!=""
  1406.       raise _INTL("Expected a number for the trainer battle ID\r\n{1}",FileLineData.linereport) if !nameline[1][/^\d+$/]
  1407.       partyid=nameline[1].to_i
  1408.     end
  1409.     FileLineData.setLine(lines[i+2],linenos[i+2])
  1410.     items=strsplit(lines[i+2],/\s*,\s*/)
  1411.     items[0].gsub!(/^\s+/,"")   # Number of Pokémon
  1412.     raise _INTL("Expected a number for the number of Pokémon\r\n{1}",FileLineData.linereport) if !items[0][/^\d+$/]
  1413.     numpoke=items[0].to_i
  1414.     realitems=[]
  1415.     for j in 1...items.length   # Items held by Trainer
  1416.       realitems.push(parseItem(items[j])) if items[j] && items[j]!=""
  1417.     end
  1418.     pkmn=[]
  1419.     for j in 0...numpoke
  1420.       FileLineData.setLine(lines[i+j+3],linenos[i+j+3])
  1421.       poke=strsplit(lines[i+j+3],/\s*,\s*/)
  1422.       begin
  1423.         # Species
  1424.         poke[TPSPECIES]=parseSpecies(poke[TPSPECIES])
  1425.       rescue
  1426.         raise _INTL("Expected a species name: {1}\r\n{2}",poke[0],FileLineData.linereport)
  1427.       end
  1428.       # Level
  1429.       poke[TPLEVEL]=poke[TPLEVEL].to_i
  1430.       raise _INTL("Bad level: {1} (must be from 1-{2})\r\n{3}",poke[TPLEVEL],
  1431.         PBExperience::MAXLEVEL,FileLineData.linereport) if poke[TPLEVEL]<=0 || poke[TPLEVEL]>PBExperience::MAXLEVEL
  1432.       # Held item
  1433.       if !poke[TPITEM] || poke[TPITEM]==""
  1434.         poke[TPITEM]=TPDEFAULTS[TPITEM]
  1435.       else
  1436.         poke[TPITEM]=parseItem(poke[TPITEM])
  1437.       end
  1438.       # Moves
  1439.       moves=[]
  1440.       for j in [TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4]
  1441.         moves.push(parseMove(poke[j])) if poke[j] && poke[j]!=""
  1442.       end
  1443.       for j in 0...4
  1444.         index=[TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4][j]
  1445.         if moves[j] && moves[j]!=0
  1446.           poke[index]=moves[j]
  1447.         else
  1448.           poke[index]=TPDEFAULTS[index]
  1449.         end
  1450.       end
  1451.       # Ability
  1452.       if !poke[TPABILITY] || poke[TPABILITY]==""
  1453.         poke[TPABILITY]=TPDEFAULTS[TPABILITY]
  1454.       else
  1455.         poke[TPABILITY]=poke[TPABILITY].to_i
  1456.         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
  1457.       end
  1458.       # Gender
  1459.       if !poke[TPGENDER] || poke[TPGENDER]==""
  1460.         poke[TPGENDER]=TPDEFAULTS[TPGENDER]
  1461.       else
  1462.         if poke[TPGENDER]=="M"
  1463.           poke[TPGENDER]=0
  1464.         elsif poke[TPGENDER]=="F"
  1465.           poke[TPGENDER]=1
  1466.         else
  1467.           poke[TPGENDER]=poke[TPGENDER].to_i
  1468.           raise _INTL("Bad genderflag: {1} (must be M or F, or 0 or 1)\r\n{2}",poke[TPGENDER],FileLineData.linereport) if poke[TPGENDER]<0 || poke[TPGENDER]>1
  1469.         end
  1470.       end
  1471.       # Form
  1472.       if !poke[TPFORM] || poke[TPFORM]==""
  1473.         poke[TPFORM]=TPDEFAULTS[TPFORM]
  1474.       else
  1475.         poke[TPFORM]=poke[TPFORM].to_i
  1476.         raise _INTL("Bad form: {1} (must be 0 or greater)\r\n{2}",poke[TPFORM],FileLineData.linereport) if poke[TPFORM]<0
  1477.       end
  1478.       # Shiny
  1479.       if !poke[TPSHINY] || poke[TPSHINY]==""
  1480.         poke[TPSHINY]=TPDEFAULTS[TPSHINY]
  1481.       elsif poke[TPSHINY]=="shiny"
  1482.         poke[TPSHINY]=true
  1483.       else
  1484.         poke[TPSHINY]=csvBoolean!(poke[TPSHINY].clone)
  1485.       end
  1486.       # Nature
  1487.       if !poke[TPNATURE] || poke[TPNATURE]==""
  1488.         poke[TPNATURE]=TPDEFAULTS[TPNATURE]
  1489.       else
  1490.         poke[TPNATURE]=parseNature(poke[TPNATURE])
  1491.       end
  1492.       # IVs
  1493.       if !poke[TPIV] || poke[TPIV]==""
  1494.         poke[TPIV]=TPDEFAULTS[TPIV]
  1495.       else
  1496.         poke[TPIV]=poke[TPIV].to_i
  1497.         raise _INTL("Bad IV: {1} (must be from 0-31)\r\n{2}",poke[TPIV],FileLineData.linereport) if poke[TPIV]<0 || poke[TPIV]>31
  1498.       end
  1499.       # Happiness
  1500.       if !poke[TPHAPPINESS] || poke[TPHAPPINESS]==""
  1501.         poke[TPHAPPINESS]=TPDEFAULTS[TPHAPPINESS]
  1502.       else
  1503.         poke[TPHAPPINESS]=poke[TPHAPPINESS].to_i
  1504.         raise _INTL("Bad happiness: {1} (must be from 0-255)\r\n{2}",poke[TPHAPPINESS],FileLineData.linereport) if poke[TPHAPPINESS]<0 || poke[TPHAPPINESS]>255
  1505.       end
  1506.       # Nickname
  1507.       if !poke[TPNAME] || poke[TPNAME]==""
  1508.         poke[TPNAME]=TPDEFAULTS[TPNAME]
  1509.       else
  1510.         poke[TPNAME]=poke[TPNAME].to_s
  1511.         raise _INTL("Bad nickname: {1} (must be 1-20 characters)\r\n{2}",poke[TPNAME],FileLineData.linereport) if (poke[TPNAME].to_s).length>20
  1512.       end
  1513.       # Shadow
  1514.       if !poke[TPSHADOW] || poke[TPSHADOW]==""
  1515.         poke[TPSHADOW]=TPDEFAULTS[TPSHADOW]
  1516.       else
  1517.         poke[TPSHADOW]=csvBoolean!(poke[TPSHADOW].clone)
  1518.       end
  1519.       # Ball
  1520.       if !poke[TPBALL] || poke[TPBALL]==""
  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(0xEF.chr)
  1920.        f.write(0xBB.chr)
  1921.        f.write(0xBF.chr)
  1922.        f.write("[DefaultTrainerList]\r\nTrainers=bttrainers.txt\r\nPokemon=btpokemon.txt\r\n")
  1923.     }
  1924.   end
  1925.   database=[]
  1926.   sections=[]
  1927.   MessageTypes.setMessagesAsHash(MessageTypes::BeginSpeech,[])
  1928.   MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechWin,[])
  1929.   MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechLose,[])
  1930.   File.open("PBS/trainerlists.txt","rb"){|f|
  1931.      pbEachFileSectionEx(f){|section,name|
  1932.         next if name!="DefaultTrainerList" && name!="TrainerList"
  1933.         rsection=[]
  1934.         for key in section.keys
  1935.           FileLineData.setSection(name,key,section[key])
  1936.           schema=btTrainersRequiredTypes[key]
  1937.           next if key=="Challenges" && name=="DefaultTrainerList"
  1938.           next if !schema
  1939.           record=pbGetCsvRecord(section[key],0,schema)
  1940.           rsection[schema[0]]=record  
  1941.         end
  1942.         if !rsection[0]
  1943.           raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
  1944.         end
  1945.         if !rsection[1]
  1946.           raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
  1947.         end
  1948.         rsection[3]=rsection[0]
  1949.         rsection[4]=rsection[1]
  1950.         rsection[5]=(name=="DefaultTrainerList")
  1951.         if safeExists?("PBS/"+rsection[0])
  1952.           rsection[0]=pbCompileBTTrainers("PBS/"+rsection[0])
  1953.         else
  1954.           rsection[0]=[]
  1955.         end
  1956.         if safeExists?("PBS/"+rsection[1])
  1957.           filename="PBS/"+rsection[1]
  1958.           rsection[1]=[]
  1959.           pbCompilerEachCommentedLine(filename){|line,lineno|
  1960.              rsection[1].push(PBPokemon.fromInspected(line))
  1961.           }
  1962.         else
  1963.           rsection[1]=[]
  1964.         end
  1965.         if !rsection[2]
  1966.           rsection[2]=[]
  1967.         end
  1968.         while rsection[2].include?("")
  1969.           rsection[2].delete("")
  1970.         end
  1971.         rsection[2].compact!
  1972.         sections.push(rsection)
  1973.      }
  1974.   }
  1975.   save_data(sections,"Data/trainerlists.dat")
  1976. end
  1977.  
  1978. def pbCompilePhoneData
  1979.   return if !safeExists?("PBS/phone.txt")
  1980.   database=PhoneDatabase.new
  1981.   sections=[]
  1982.   File.open("PBS/phone.txt","rb"){|f|
  1983.      pbEachSection(f){|section,name|
  1984.         if name=="<Generics>"
  1985.           database.generics=section
  1986.           sections.concat(section)
  1987.         elsif name=="<BattleRequests>"
  1988.           database.battleRequests=section
  1989.           sections.concat(section)
  1990.         elsif name=="<GreetingsMorning>"
  1991.           database.greetingsMorning=section
  1992.           sections.concat(section)
  1993.         elsif name=="<GreetingsEvening>"
  1994.           database.greetingsEvening=section
  1995.           sections.concat(section)
  1996.         elsif name=="<Greetings>"
  1997.           database.greetings=section
  1998.           sections.concat(section)
  1999.         elsif name=="<Bodies1>"
  2000.           database.bodies1=section
  2001.           sections.concat(section)
  2002.         elsif name=="<Bodies2>"
  2003.           database.bodies2=section
  2004.           sections.concat(section)
  2005.         end
  2006.      }
  2007.   }
  2008.   MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages,sections)
  2009.   save_data(database,"Data/phone.dat")
  2010. end
  2011.  
  2012. def frozenArrayValue(arr)
  2013.   typestring=""
  2014.   for i in 0...arr.length
  2015.     if i>0
  2016.       typestring+=((i%20)==0) ? ",\r\n" : ","
  2017.     end
  2018.     typestring+=arr[i].to_s
  2019.   end
  2020.   return "["+typestring+"].freeze"
  2021. end
  2022.  
  2023. def pbWriteDefaultTypes
  2024.   if !safeExists?("PBS/types.txt")
  2025.     File.open("PBS/types.txt","w"){|f|
  2026.        f.write(0xEF.chr)
  2027.        f.write(0xBB.chr)
  2028.        f.write(0xBF.chr)
  2029. fx=<<END
  2030. [0]
  2031. Name=Normal
  2032. InternalName=NORMAL
  2033. Weaknesses=FIGHTING
  2034. Immunities=GHOST
  2035.  
  2036. [1]
  2037. Name=Fighting
  2038. InternalName=FIGHTING
  2039. Weaknesses=FLYING,PSYCHIC
  2040. Resistances=ROCK,BUG,DARK
  2041.  
  2042. [2]
  2043. Name=Flying
  2044. InternalName=FLYING
  2045. Weaknesses=ROCK,ELECTRIC,ICE
  2046. Resistances=FIGHTING,BUG,GRASS
  2047. Immunities=GROUND
  2048.  
  2049. [3]
  2050. Name=Poison
  2051. InternalName=POISON
  2052. Weaknesses=GROUND,PSYCHIC
  2053. Resistances=FIGHTING,POISON,BUG,GRASS
  2054.  
  2055. [4]
  2056. Name=Ground
  2057. InternalName=GROUND
  2058. Weaknesses=WATER,GRASS,ICE
  2059. Resistances=POISON,ROCK
  2060. Immunities=ELECTRIC
  2061.  
  2062. [5]
  2063. Name=Rock
  2064. InternalName=ROCK
  2065. Weaknesses=FIGHTING,GROUND,STEEL,WATER,GRASS
  2066. Resistances=NORMAL,FLYING,POISON,FIRE
  2067.  
  2068. [6]
  2069. Name=Bug
  2070. InternalName=BUG
  2071. Weaknesses=FLYING,ROCK,FIRE
  2072. Resistances=FIGHTING,GROUND,GRASS
  2073.  
  2074. [7]
  2075. Name=Ghost
  2076. InternalName=GHOST
  2077. Weaknesses=GHOST,DARK
  2078. Resistances=POISON,BUG
  2079. Immunities=NORMAL,FIGHTING
  2080.  
  2081. [8]
  2082. Name=Steel
  2083. InternalName=STEEL
  2084. Weaknesses=FIGHTING,GROUND,FIRE
  2085. Resistances=NORMAL,FLYING,ROCK,BUG,GHOST,STEEL,GRASS,PSYCHIC,ICE,DRAGON,DARK
  2086. Immunities=POISON
  2087.  
  2088. [9]
  2089. Name=???
  2090. InternalName=QMARKS
  2091. IsPseudoType=true
  2092.  
  2093. [10]
  2094. Name=Fire
  2095. InternalName=FIRE
  2096. IsSpecialType=true
  2097. Weaknesses=GROUND,ROCK,WATER
  2098. Resistances=BUG,STEEL,FIRE,GRASS,ICE
  2099.  
  2100. [11]
  2101. Name=Water
  2102. InternalName=WATER
  2103. IsSpecialType=true
  2104. Weaknesses=GRASS,ELECTRIC
  2105. Resistances=STEEL,FIRE,WATER,ICE
  2106.  
  2107. [12]
  2108. Name=Grass
  2109. InternalName=GRASS
  2110. IsSpecialType=true
  2111. Weaknesses=FLYING,POISON,BUG,FIRE,ICE
  2112. Resistances=GROUND,WATER,GRASS,ELECTRIC
  2113.  
  2114. [13]
  2115. Name=Electric
  2116. InternalName=ELECTRIC
  2117. IsSpecialType=true
  2118. Weaknesses=GROUND
  2119. Resistances=FLYING,STEEL,ELECTRIC
  2120.  
  2121. [14]
  2122. Name=Psychic
  2123. InternalName=PSYCHIC
  2124. IsSpecialType=true
  2125. Weaknesses=BUG,GHOST,DARK
  2126. Resistances=FIGHTING,PSYCHIC
  2127.  
  2128. [15]
  2129. Name=Ice
  2130. InternalName=ICE
  2131. IsSpecialType=true
  2132. Weaknesses=FIGHTING,ROCK,STEEL,FIRE
  2133. Resistances=ICE
  2134.  
  2135. [16]
  2136. Name=Dragon
  2137. InternalName=DRAGON
  2138. IsSpecialType=true
  2139. Weaknesses=ICE,DRAGON
  2140. Resistances=FIRE,WATER,GRASS,ELECTRIC
  2141.  
  2142. [17]
  2143. Name=Dark
  2144. InternalName=DARK
  2145. IsSpecialType=true
  2146. Weaknesses=FIGHTING,BUG
  2147. Resistances=GHOST,DARK
  2148. Immunities=PSYCHIC
  2149.  
  2150. END
  2151.        f.write(fx)
  2152.     }
  2153.   end
  2154. end
  2155.  
  2156. def pbCompileTypes
  2157.   pbWriteDefaultTypes
  2158.   sections=[]
  2159.   typechart=[]
  2160.   types=[]
  2161.   nameToType={}
  2162.   requiredtypes={
  2163.      "Name"=>[1,"s"],
  2164.      "InternalName"=>[2,"s"],
  2165.   }
  2166.   optionaltypes={
  2167.      "IsPseudoType"=>[3,"b"],
  2168.      "IsSpecialType"=>[4,"b"],
  2169.      "Weaknesses"=>[5,"*s"],
  2170.      "Resistances"=>[6,"*s"],
  2171.      "Immunities"=>[7,"*s"]
  2172.   }
  2173.   currentmap=-1
  2174.   foundtypes=[]
  2175.   pbCompilerEachCommentedLine("PBS/types.txt") {|line,lineno|
  2176.      if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
  2177.        sectionname=$~[1]
  2178.        if currentmap>=0
  2179.          for reqtype in requiredtypes.keys
  2180.            if !foundtypes.include?(reqtype)
  2181.              raise _INTL("Required value '{1}' not given in section '{2}'\r\n{3}",reqtype,currentmap,FileLineData.linereport)
  2182.            end
  2183.          end
  2184.          foundtypes.clear
  2185.        end
  2186.        currentmap=sectionname.to_i
  2187.        types[currentmap]=[currentmap,nil,nil,false,false,[],[],[]]
  2188.      else
  2189.        if currentmap<0
  2190.          raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
  2191.        end
  2192.        if !line[/^\s*(\w+)\s*=\s*(.*)$/]
  2193.          raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
  2194.        end
  2195.        matchData=$~
  2196.        schema=nil
  2197.        FileLineData.setSection(currentmap,matchData[1],matchData[2])
  2198.        if requiredtypes.keys.include?(matchData[1])
  2199.          schema=requiredtypes[matchData[1]]
  2200.          foundtypes.push(matchData[1])
  2201.        else
  2202.          schema=optionaltypes[matchData[1]]
  2203.        end
  2204.        if schema
  2205.          record=pbGetCsvRecord(matchData[2],lineno,schema)
  2206.          types[currentmap][schema[0]]=record
  2207.        end
  2208.      end
  2209.   }
  2210.   types.compact!
  2211.   maxValue=0
  2212.   for type in types; maxValue=[maxValue,type[0]].max; end
  2213.   pseudotypes=[]
  2214.   specialtypes=[]
  2215.   typenames=[]
  2216.   typeinames=[]
  2217.   typehash={}
  2218.   for type in types
  2219.     pseudotypes.push(type[0]) if type[3]
  2220.     typenames[type[0]]=type[1]
  2221.     typeinames[type[0]]=type[2]
  2222.     typehash[type[0]]=type
  2223.   end
  2224.   for type in types
  2225.     n=type[1]
  2226.     for w in type[5]; if !typeinames.include?(w)
  2227.       raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Weaknesses)",w,n)
  2228.     end; end
  2229.     for w in type[6]; if !typeinames.include?(w)
  2230.       raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Resistances)",w,n)
  2231.     end; end
  2232.     for w in type[7]; if !typeinames.include?(w)
  2233.       raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Immunities)",w,n)
  2234.     end; end
  2235.   end
  2236.   for i in 0..maxValue
  2237.     pseudotypes.push(i) if !typehash[i]
  2238.   end
  2239.   pseudotypes.sort!
  2240.   for type in types; specialtypes.push(type[0]) if type[4]; end
  2241.   specialtypes.sort!
  2242.   MessageTypes.setMessages(MessageTypes::Types,typenames)
  2243.   code="class PBTypes\r\n"
  2244.   for type in types
  2245.     code+="#{type[2]}=#{type[0]}\r\n"
  2246.   end
  2247.   code+="def PBTypes.getCount; return #{types.length}; end\r\n"
  2248.   code+="def PBTypes.maxValue; return #{maxValue}; end\r\n"
  2249.   code+="def PBTypes.getName(id)\r\nreturn pbGetMessage(MessageTypes::Types,id)\r\nend\r\n"
  2250.   count=maxValue+1
  2251.   for i in 0...count
  2252.     type=typehash[i]
  2253.     j=0; k=i; while j<count
  2254.       typechart[k]=2
  2255.       atype=typehash[j]
  2256.       if type && atype
  2257.         typechart[k]=4 if type[5].include?(atype[2]) # weakness
  2258.         typechart[k]=1 if type[6].include?(atype[2]) # resistance
  2259.         typechart[k]=0 if type[7].include?(atype[2]) # immune
  2260.       end
  2261.       j+=1
  2262.       k+=count
  2263.     end
  2264.   end
  2265.   code+="end\r\n"
  2266.   eval(code)
  2267.   save_data([pseudotypes,specialtypes,typechart],"Data/types.dat")
  2268.   pbAddScript(code,"PBTypes")
  2269.   Graphics.update
  2270. end
  2271.  
  2272. def pbCompilePokemonData
  2273.   # Free bytes: 0, 1, 17, 29, 30, 37, 56-75
  2274.   sections=[]
  2275.   requiredtypes={
  2276.      "Name"=>[0,"s"],
  2277.      "Kind"=>[0,"s"],
  2278.      "InternalName"=>[0,"c"],
  2279.      "Pokedex"=>[0,"S"],
  2280.      "Moves"=>[0,"*uE",nil,PBMoves],
  2281.      "Color"=>[6,"e",PBColors],
  2282.      "Type1"=>[8,"e",PBTypes],
  2283.      "BaseStats"=>[10,"uuuuuu"],
  2284.      "Rareness"=>[16,"u"],
  2285.      "GenderRate"=>[18,"e",{"AlwaysMale"=>0,"FemaleOneEighth"=>31,
  2286.         "Female25Percent"=>63,"Female50Percent"=>127,"Female75Percent"=>191,
  2287.         "FemaleSevenEighths"=>223,"AlwaysFemale"=>254,"Genderless"=>255}],
  2288.      "Happiness"=>[19,"u"],
  2289.      "GrowthRate"=>[20,"e",{"Medium"=>0,"MediumFast"=>0,"Erratic"=>1,
  2290.         "Fluctuating"=>2,"Parabolic"=>3,"MediumSlow"=>3,"Fast"=>4,"Slow"=>5}],
  2291.      "StepsToHatch"=>[21,"w"],
  2292.      "EffortPoints"=>[23,"uuuuuu"],
  2293.      "Compatibility"=>[31,"eg",PBEggGroups,PBEggGroups],
  2294.      "Height"=>[33,"f"],
  2295.      "Weight"=>[35,"f"],
  2296.      "BaseEXP"=>[38,"w"],
  2297.   }
  2298.   optionaltypes={
  2299.      "BattlerPlayerY"=>[0,"i"],
  2300.      "BattlerEnemyY"=>[0,"i"],
  2301.      "BattlerAltitude"=>[0,"i"],
  2302.      "EggMoves"=>[0,"*E",PBMoves],
  2303.      "FormNames"=>[0,"S"],
  2304.      "RegionalNumbers"=>[0,"*w"],
  2305.      "Evolutions"=>[0,"*ses",nil,PBEvolution],
  2306.      "Abilities"=>[2,"EG",PBAbilities,PBAbilities],
  2307.      "Habitat"=>[7,"e",["","Grassland","Forest","WatersEdge","Sea","Cave","Mountain","RoughTerrain","Urban","Rare"]],
  2308.      "Type2"=>[9,"e",PBTypes],
  2309.      "HiddenAbility"=>[40,"EGGG",PBAbilities,PBAbilities,PBAbilities,PBAbilities],
  2310.      "WildItemCommon"=>[48,"E",PBItems],
  2311.      "WildItemUncommon"=>[50,"E",PBItems],
  2312.      "WildItemRare"=>[52,"E",PBItems],
  2313.      "Incense"=>[54,"E",PBItems]
  2314.   }
  2315.   currentmap=-1
  2316.   dexdatas=[]
  2317.   eggmoves=[]
  2318.   entries=[]
  2319.   kinds=[]
  2320.   speciesnames=[]
  2321.   moves=[]
  2322.   evolutions=[]
  2323.   regionals=[]
  2324.   formnames=[]
  2325.   metrics=[SignedWordArray.new,SignedWordArray.new,SignedWordArray.new]
  2326.   constants=""
  2327.   maxValue=0
  2328.   File.open("PBS/pokemon.txt","rb"){|f|
  2329.      FileLineData.file="PBS/pokemon.txt"
  2330.      pbEachFileSection(f){|lastsection,currentmap|
  2331.         dexdata=[]
  2332.         for i in 0...76
  2333.           dexdata[i]=0
  2334.         end
  2335.         thesemoves=[]
  2336.         theseevos=[]
  2337.         if !lastsection["Type2"] || lastsection["Type2"]==""
  2338.           if !lastsection["Type1"] || lastsection["Type1"]==""
  2339.             raise _INTL("No Pokémon type is defined in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
  2340.             next
  2341.           end
  2342.           lastsection["Type2"]=lastsection["Type1"].clone
  2343.         end
  2344.         [requiredtypes,optionaltypes].each{|hash|
  2345.            for key in hash.keys
  2346.              FileLineData.setSection(currentmap,key,lastsection[key])
  2347.              maxValue=[maxValue,currentmap].max
  2348.              sectionDisplay=currentmap.to_s
  2349.              next if hash[key][0]<0
  2350.              if currentmap==0
  2351.                raise _INTL("A Pokemon species can't be numbered 0 (PBS/pokemon.txt)")
  2352.              end
  2353.              if !lastsection[key] || lastsection[key]==""
  2354.                raise _INTL("Required entry {1} is missing or empty in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
  2355.                next
  2356.              end
  2357.              secvalue=lastsection[key]
  2358.              rtschema=hash[key]
  2359.              schema=hash[key][1]
  2360.              valueindex=0
  2361.              loop do
  2362.                offset=0
  2363.                for i in 0...schema.length
  2364.                  next if schema[i,1]=="*"
  2365.                  minus1=(schema[0,1]=="*") ? -1 : 0
  2366.                  if (schema[i,1]=="g" || schema[i,1]=="G") && secvalue==""
  2367.                    if key=="Compatibility"
  2368.                      dexdata[rtschema[0]+offset]=dexdata[rtschema[0]]
  2369.                    end
  2370.                    break
  2371.                  end
  2372.                  case schema[i,1]
  2373.                  when "e", "g"
  2374.                    value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
  2375.                    bytes=1
  2376.                  when "E", "G"
  2377.                    value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
  2378.                    bytes=2
  2379.                  when "i"
  2380.                    value=csvInt!(secvalue,key)
  2381.                    bytes=1
  2382.                  when "u"
  2383.                    value=csvPosInt!(secvalue,key)
  2384.                    bytes=1
  2385.                  when "w"
  2386.                    value=csvPosInt!(secvalue,key)
  2387.                    bytes=2
  2388.                  when "f"
  2389.                    value=csvFloat!(secvalue,key,sectionDisplay)
  2390.                    value=(value*10).round
  2391.                    if value<=0
  2392.                      raise _INTL("Value '{1}' can't be less than or close to 0 (section {2}, PBS/pokemon.txt)",key,currentmap)
  2393.                    end
  2394.                    bytes=2
  2395.                  when "c", "s"
  2396.                    value=csvfield!(secvalue)
  2397.                  when "S"
  2398.                    value=secvalue
  2399.                    secvalue=""
  2400.                  end
  2401.                  if key=="EggMoves"
  2402.                    eggmoves[currentmap]=[] if !eggmoves[currentmap]
  2403.                    eggmoves[currentmap].push(value)
  2404.                  elsif key=="Moves"
  2405.                    thesemoves.push(value)
  2406.                  elsif key=="RegionalNumbers"
  2407.                    regionals[valueindex]=[] if !regionals[valueindex]
  2408.                    regionals[valueindex][currentmap]=value
  2409.                  elsif key=="Evolutions"
  2410.                    theseevos.push(value)
  2411.                  elsif key=="InternalName"
  2412.                    raise _INTL("Invalid internal name: {1} (section {2}, PBS/pokemon.txt)",value,currentmap) if !value[/^(?![0-9])\w*$/]
  2413.                    constants+="#{value}=#{currentmap}\r\n"
  2414.                  elsif key=="Kind"
  2415.                    raise _INTL("Kind {1} is greater than 20 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>20
  2416.                    kinds[currentmap]=value
  2417.                  elsif key=="Pokedex"
  2418.                    entries[currentmap]=value
  2419.                  elsif key=="BattlerPlayerY"
  2420.                    pbCheckSignedWord(value,key)
  2421.                    metrics[0][currentmap]=value
  2422.                  elsif key=="BattlerEnemyY"
  2423.                    pbCheckSignedWord(value,key)
  2424.                    metrics[1][currentmap]=value
  2425.                  elsif key=="BattlerAltitude"
  2426.                    pbCheckSignedWord(value,key)
  2427.                    metrics[2][currentmap]=value
  2428.                  elsif key=="Name"
  2429.                    raise _INTL("Species name {1} is greater than 20 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>20
  2430.                    speciesnames[currentmap]=value
  2431.                  elsif key=="FormNames"
  2432.                    formnames[currentmap]=value
  2433.                  else
  2434.                    dexdata[rtschema[0]+offset]=value&0xFF
  2435.                    dexdata[rtschema[0]+1+offset]=(value>>8)&0xFF if bytes>1
  2436.                    offset+=bytes
  2437.                  end
  2438.                  valueindex+=1
  2439.                end
  2440.                break if secvalue==""
  2441.                break if schema[0,1]!="*"
  2442.              end
  2443.            end
  2444.         }
  2445.         movelist=[]
  2446.         evolist=[]
  2447.         for i in 0...thesemoves.length/2
  2448.           movelist.push([thesemoves[i*2],thesemoves[i*2+1],i])
  2449.         end
  2450.         movelist.sort!{|a,b| a[0]==b[0] ? a[2]<=>b[2] : a[0]<=>b[0]}
  2451.         for i in movelist; i.pop; end
  2452.         for i in 0...theseevos.length/3
  2453.           evolist.push([theseevos[i*3],theseevos[i*3+1],theseevos[i*3+2]])
  2454.         end
  2455.         moves[currentmap]=movelist
  2456.         evolutions[currentmap]=evolist
  2457.         dexdatas[currentmap]=dexdata
  2458.      }
  2459.   }
  2460.   if dexdatas.length==0
  2461.     raise _INTL("No Pokémon species are defined in pokemon.txt")
  2462.   end
  2463.   count=dexdatas.compact.length
  2464.   code="module PBSpecies\r\n#{constants}"
  2465.   for i in 0...speciesnames.length
  2466.     speciesnames[i]="????????" if !speciesnames[i]
  2467.   end
  2468.   code+="def PBSpecies.getName(id)\r\nreturn pbGetMessage(MessageTypes::Species,id)\r\nend\r\n"
  2469.   code+="def PBSpecies.getCount\r\nreturn #{count}\r\nend\r\n"
  2470.   code+="def PBSpecies.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  2471.   eval(code)
  2472.   pbAddScript(code,"PBSpecies")
  2473.   for e in 0...evolutions.length
  2474.     evolist=evolutions[e]
  2475.     next if !evolist
  2476.     for i in 0...evolist.length
  2477.       FileLineData.setSection(i,"Evolutions","")
  2478.       evonib=evolist[i][1]
  2479.       evolist[i][0]=csvEnumField!(evolist[i][0],PBSpecies,"Evolutions",i)
  2480.       case PBEvolution::EVOPARAM[evonib]
  2481.       when 1
  2482.         evolist[i][2]=csvPosInt!(evolist[i][2])
  2483.       when 2
  2484.         evolist[i][2]=csvEnumField!(evolist[i][2],PBItems,"Evolutions",i)
  2485.       when 3
  2486.         evolist[i][2]=csvEnumField!(evolist[i][2],PBMoves,"Evolutions",i)
  2487.       when 4
  2488.         evolist[i][2]=csvEnumField!(evolist[i][2],PBSpecies,"Evolutions",i)
  2489.       when 5
  2490.         evolist[i][2]=csvEnumField!(evolist[i][2],PBTypes,"Evolutions",i)
  2491.       else
  2492.         evolist[i][2]=0
  2493.       end
  2494.       evolist[i][3]=0
  2495.     end
  2496.   end
  2497.   _EVODATAMASK=0xC0
  2498.   _EVONEXTFORM=0x00
  2499.   _EVOPREVFORM=0x40
  2500.   for e in 0...evolutions.length
  2501.     evolist=evolutions[e]
  2502.     next if !evolist
  2503.     parent=nil
  2504.     child=-1
  2505.     for f in 0...evolutions.length
  2506.       evolist=evolutions[f]
  2507.       next if !evolist || e==f
  2508.       for g in evolist
  2509.         if g[0]==e && (g[3]&_EVODATAMASK)==_EVONEXTFORM
  2510.           parent=g
  2511.           child=f
  2512.           break
  2513.         end
  2514.       end
  2515.       break if parent
  2516.     end
  2517.     if parent
  2518.       evolutions[e]=[[child,parent[1],parent[2],_EVOPREVFORM]].concat(evolutions[e])
  2519.     end
  2520.   end
  2521.   metrics[0].fillNils(dexdatas.length,0) # player Y
  2522.   metrics[1].fillNils(dexdatas.length,0) # enemy Y
  2523.   metrics[2].fillNils(dexdatas.length,0) # altitude
  2524.   save_data(metrics,"Data/metrics.dat")
  2525.   File.open("Data/regionals.dat","wb"){|f|
  2526.      f.fputw(regionals.length)
  2527.      f.fputw(dexdatas.length)
  2528.      for i in 0...regionals.length
  2529.        for j in 0...dexdatas.length
  2530.          num=regionals[i][j]
  2531.          num=0 if !num
  2532.          f.fputw(num)
  2533.        end
  2534.      end
  2535.   }
  2536.   File.open("Data/evolutions.dat","wb"){|f|
  2537.      mx=[maxValue,evolutions.length-1].max
  2538.      offset=mx*8
  2539.      for i in 1..mx
  2540.        f.fputdw(offset)
  2541.        f.fputdw(evolutions[i] ? evolutions[i].length*5 : 0)
  2542.        offset+=evolutions[i] ? evolutions[i].length*5 : 0
  2543.      end
  2544.      for i in 1..mx
  2545.        next if !evolutions[i]
  2546.        for j in evolutions[i]
  2547.          f.fputb(j[3]|j[1])
  2548.          f.fputw(j[2])
  2549.          f.fputw(j[0])
  2550.        end
  2551.      end
  2552.   }
  2553.   File.open("Data/dexdata.dat","wb"){|f|
  2554.      mx=[maxValue,dexdatas.length-1].max
  2555.      for i in 1..mx
  2556.        if dexdatas[i]
  2557.          dexdatas[i].each {|item| f.fputb(item)}
  2558.        else
  2559.          76.times { f.fputb(0) }
  2560.        end
  2561.      end
  2562.   }
  2563.   File.open("Data/eggEmerald.dat","wb"){|f|
  2564.      mx=[maxValue,eggmoves.length-1].max
  2565.      offset=mx*8
  2566.      for i in 1..mx
  2567.        f.fputdw(offset)
  2568.        f.fputdw(eggmoves[i] ? eggmoves[i].length : 0)
  2569.        offset+=eggmoves[i] ? eggmoves[i].length*2 : 0
  2570.      end
  2571.      for i in 1..mx
  2572.        next if !eggmoves[i]
  2573.        for j in eggmoves[i]
  2574.          f.fputw(j)
  2575.        end
  2576.      end
  2577.   }
  2578.   MessageTypes.setMessages(MessageTypes::Species,speciesnames)
  2579.   MessageTypes.setMessages(MessageTypes::Kinds,kinds)
  2580.   MessageTypes.setMessages(MessageTypes::Entries,entries)
  2581.   MessageTypes.setMessages(MessageTypes::FormNames,formnames)
  2582.   File.open("Data/attacksRS.dat","wb"){|f|
  2583.      mx=[maxValue,moves.length-1].max
  2584.      offset=mx*8
  2585.      for i in 1..mx
  2586.        f.fputdw(offset)
  2587.        f.fputdw(moves[i] ? moves[i].length*2 : 0)
  2588.        offset+=moves[i] ? moves[i].length*4 : 0
  2589.      end
  2590.      for i in 1..mx
  2591.        next if !moves[i]
  2592.        for j in moves[i]
  2593.          f.fputw(j[0])
  2594.          f.fputw(j[1])
  2595.        end
  2596.      end
  2597.   }
  2598. end
  2599.  
  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.    "Constants.rxdata"
  2620. ]
  2621.  
  2622. textfiles=[
  2623.    "moves.txt",
  2624.    "abilities.txt",
  2625.    "encounters.txt",
  2626.    "trainers.txt",
  2627.    "trainertypes.txt",
  2628.    "items.txt",
  2629.    "connections.txt",
  2630.    "metadata.txt",
  2631.    "townmap.txt",
  2632.    "pokemon.txt",
  2633.    "phone.txt",
  2634.    "trainerlists.txt",
  2635.    "shadowmoves.txt",
  2636.    "tm.txt",
  2637.    "types.txt"
  2638. ]
  2639.  
  2640. begin
  2641.  
  2642. def pbGenerateMoveRoute(commands)
  2643.   route=RPG::MoveRoute.new
  2644.   route.repeat=false
  2645.   route.skippable=true
  2646.   route.list.clear
  2647.   i=0; while i<commands.length
  2648.     case commands[i]
  2649.     when PBMoveRoute::Wait, PBMoveRoute::SwitchOn, PBMoveRoute::SwitchOff,
  2650.          PBMoveRoute::ChangeSpeed, PBMoveRoute::ChangeFreq, PBMoveRoute::Opacity,
  2651.          PBMoveRoute::Blending, PBMoveRoute::PlaySE, PBMoveRoute::Script
  2652.       route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1]]))
  2653.       i+=1
  2654.     when PBMoveRoute::ScriptAsync
  2655.       route.list.push(RPG::MoveCommand.new(PBMoveRoute::Script,[commands[i+1]]))
  2656.       route.list.push(RPG::MoveCommand.new(PBMoveRoute::Wait,[0]))
  2657.       i+=1
  2658.     when PBMoveRoute::Jump
  2659.       route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2]]))
  2660.       i+=2
  2661.     when PBMoveRoute::Graphic
  2662.       route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2],commands[i+3],commands[i+4]]))
  2663.       i+=4
  2664.     else
  2665.       route.list.push(RPG::MoveCommand.new(commands[i]))
  2666.     end
  2667.     i+=1
  2668.   end
  2669.   route.list.push(RPG::MoveCommand.new(0))
  2670.   return route
  2671. end
  2672.  
  2673. def pbPushMoveRoute(list,character,route,indent=0)
  2674.   if route.is_a?(Array)
  2675.     route=pbGenerateMoveRoute(route)
  2676.   end
  2677.   for i in 0...route.list.length
  2678.     list.push(RPG::EventCommand.new(
  2679.        i==0 ? 209 : 509,indent,
  2680.        i==0 ? [character,route] : [route.list[i-1]]))
  2681.   end
  2682. end
  2683.  
  2684. def pbPushMoveRouteAndWait(list,character,route,indent=0)
  2685.   pbPushMoveRoute(list,character,route,indent)
  2686.   pbPushEvent(list,210,[],indent)
  2687. end
  2688.  
  2689. def pbPushWait(list,frames,indent=0)
  2690.   pbPushEvent(list,106,[frames],indent)
  2691. end
  2692.  
  2693. def pbPushEvent(list,cmd,params=nil,indent=0)
  2694.   list.push(RPG::EventCommand.new(cmd,indent,params ? params : []))
  2695. end
  2696.  
  2697. def pbPushEnd(list)
  2698.   list.push(RPG::EventCommand.new(0,0,[]))
  2699. end
  2700.  
  2701. def pbPushComment(list,cmt,indent=0)
  2702.   textsplit2=cmt.split(/\n/)
  2703.   for i in 0...textsplit2.length
  2704.     list.push(RPG::EventCommand.new(i==0 ? 108 : 408,indent,[textsplit2[i].gsub(/\s+$/,"")]))
  2705.   end
  2706. end
  2707.  
  2708. def pbPushText(list,text,indent=0)
  2709.   return if !text
  2710.   textsplit=text.split(/\\m/)
  2711.   for t in textsplit
  2712.     first=true
  2713.     if $RPGVX
  2714.       list.push(RPG::EventCommand.new(101,indent,["",0,0,2]))
  2715.       first=false
  2716.     end
  2717.     textsplit2=t.split(/\n/)
  2718.     for i in 0...textsplit2.length
  2719.       textchunk=textsplit2[i].gsub(/\s+$/,"")
  2720.       if textchunk && textchunk!=""
  2721.         list.push(RPG::EventCommand.new(first ? 101 : 401,indent,[textchunk]))
  2722.         first=false
  2723.       end
  2724.     end
  2725.   end
  2726. end
  2727.  
  2728. def pbPushScript(list,script,indent=0)
  2729.   return if !script
  2730.   first=true
  2731.   textsplit2=script.split(/\n/)
  2732.   for i in 0...textsplit2.length
  2733.     textchunk=textsplit2[i].gsub(/\s+$/,"")
  2734.     if textchunk && textchunk!=""
  2735.       list.push(RPG::EventCommand.new(first ? 355 : 655,indent,[textchunk]))
  2736.       first=false
  2737.     end
  2738.   end
  2739. end
  2740.  
  2741. def pbPushExit(list,indent=0)
  2742.   list.push(RPG::EventCommand.new(115,indent,[]))
  2743. end
  2744.  
  2745. def pbPushElse(list,indent=0)
  2746.   list.push(RPG::EventCommand.new(0,indent,[]))
  2747.   list.push(RPG::EventCommand.new(411,indent-1,[]))
  2748. end
  2749.  
  2750. def pbPushBranchEnd(list,indent=0)
  2751.   list.push(RPG::EventCommand.new(0,indent,[]))
  2752.   list.push(RPG::EventCommand.new(412,indent-1,[]))
  2753. end
  2754.  
  2755. def pbPushBranch(list,script,indent=0)
  2756.   list.push(RPG::EventCommand.new(111,indent,[12,script]))
  2757. end
  2758.  
  2759. def pbPushSelfSwitch(list,swtch,switchOn,indent=0)
  2760.   list.push(RPG::EventCommand.new(123,indent,[swtch,switchOn ? 0 : 1]))
  2761. end
  2762.  
  2763. def safequote(x)
  2764.   x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  2765.  x=x.gsub(/\t/,"\\t")
  2766.  x=x.gsub(/\r/,"\\r")
  2767.  x=x.gsub(/\n/,"\\n")
  2768.  return x
  2769. end
  2770.  
  2771. def safequote2(x)
  2772.  x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  2773.  x=x.gsub(/\t/,"\\t")
  2774.  x=x.gsub(/\r/,"\\r")
  2775.  x=x.gsub(/\n/," ")
  2776.  return x
  2777. end
  2778.  
  2779. def pbEventId(event)
  2780.  list=event.pages[0].list
  2781.  return nil if list.length==0
  2782.  codes=[]
  2783.  i=0;while i<list.length
  2784.    codes.push(list[i].code)
  2785.    i+=1
  2786.  end
  2787. end
  2788.  
  2789.  
  2790.  
  2791. class MapData
  2792.  def initialize
  2793.    @mapinfos=pbLoadRxData("Data/MapInfos")
  2794.    @system=pbLoadRxData("Data/System")
  2795.    @tilesets=pbLoadRxData("Data/Tilesets")
  2796.    @mapxy=[]
  2797.    @mapWidths=[]
  2798.    @mapHeights=[]
  2799.    @maps=[]
  2800.    @registeredSwitches={}
  2801.  end
  2802.  
  2803.  def registerSwitch(switch)
  2804.    if @registeredSwitches[switch]
  2805.      return @registeredSwitches[switch]
  2806.    end
  2807.    for id in 1..5000
  2808.      name=@system.switches[id]
  2809.      if !name || name=="" || name==switch
  2810.        @system.switches[id]=switch
  2811.        @registeredSwitches[switch]=id
  2812.        return id
  2813.      end
  2814.    end
  2815.    return 1
  2816.  end
  2817.  
  2818.  def saveTilesets
  2819.    filename="Data/Tilesets"
  2820.    if $RPGVX
  2821.      filename+=".rvdata"
  2822.    else
  2823.      filename+=".rxdata"
  2824.    end
  2825.    save_data(@tilesets,filename)
  2826.    filename="Data/System"
  2827.    if $RPGVX
  2828.      filename+=".rvdata"
  2829.    else
  2830.      filename+=".rxdata"
  2831.    end
  2832.    save_data(@system,filename)
  2833.  end
  2834.  
  2835.  def switchName(id)
  2836.    return @system.switches[id] || ""
  2837.  end
  2838.  
  2839.  def mapFilename(mapID)
  2840.    filename=sprintf("Data/map%03d",mapID)
  2841.    if $RPGVX
  2842.      filename+=".rvdata"
  2843.    else
  2844.      filename+=".rxdata"
  2845.    end
  2846.    return filename
  2847.  end
  2848.  
  2849.  def getMap(mapID)
  2850.    if @maps[mapID]
  2851.      return @maps[mapID]
  2852.    else
  2853.      begin
  2854.        @maps[mapID]=load_data(mapFilename(mapID))
  2855.        return @maps[mapID]
  2856.      rescue
  2857.        return nil
  2858.      end
  2859.    end
  2860.  end
  2861.  
  2862.  def isPassable?(mapID,x,y)
  2863.    if !$RPGVX
  2864.      map=getMap(mapID)
  2865.      return false if !map
  2866.      return false if x<0 || x>=map.width || y<0 || y>=map.height
  2867.      passages=@tilesets[map.tileset_id].passages
  2868.      priorities=@tilesets[map.tileset_id].priorities
  2869.      for i in [2, 1, 0]
  2870.        tile_id = map.data[x, y, i]
  2871.        return false if tile_id == nil
  2872.        return false if passages[tile_id] & 0x0f == 0x0f
  2873.        return true if priorities[tile_id] == 0
  2874.      end
  2875.    end
  2876.    return true
  2877.  end
  2878.  
  2879.  def setCounterTile(mapID,x,y)
  2880.    if !$RPGVX
  2881.      map=getMap(mapID)
  2882.      return if !map
  2883.      passages=@tilesets[map.tileset_id].passages
  2884.      for i in [2, 1, 0]
  2885.        tile_id = map.data[x, y, i]
  2886.        next if tile_id == 0 || tile_id==nil || !passages[tile_id]
  2887.        passages[tile_id]|=0x80
  2888.        break
  2889.      end
  2890.    end
  2891.  end
  2892.  
  2893.  def isCounterTile?(mapID,x,y)
  2894.    return false if $RPGVX
  2895.    map=getMap(mapID)
  2896.    return false if !map
  2897.    passages=@tilesets[map.tileset_id].passages
  2898.    for i in [2, 1, 0]
  2899.      tile_id = map.data[x, y, i]
  2900.      return false if tile_id == nil
  2901.      return true if passages[tile_id] && passages[tile_id] & 0x80 == 0x80
  2902.    end
  2903.    return false
  2904.  end
  2905.  
  2906.  def saveMap(mapID)
  2907.    save_data(getMap(mapID),mapFilename(mapID)) rescue nil
  2908.  end
  2909.  
  2910.  def getEventFromXY(mapID,x,y)
  2911.    return nil if x<0 || y<0
  2912.    mapPositions=@mapxy[mapID]
  2913.    if mapPositions
  2914.      return mapPositions[y*@mapWidths[mapID]+x]
  2915.    else
  2916.      map=getMap(mapID)
  2917.      return nil if !map
  2918.      @mapWidths[mapID]=map.width
  2919.      @mapHeights[mapID]=map.height
  2920.      mapPositions=[]
  2921.      width=map.width
  2922.      for e in map.events.values
  2923.        mapPositions[e.y*width+e.x]=e if e
  2924.      end
  2925.      @mapxy[mapID]=mapPositions
  2926.      return mapPositions[y*width+x]
  2927.    end
  2928.  end
  2929.  
  2930.  def getEventFromID(mapID,id)
  2931.    map=getMap(mapID)
  2932.    return nil if !map
  2933.    return map.events[id]
  2934.  end
  2935.  
  2936.  def mapinfos
  2937.    return @mapinfos
  2938.  end
  2939. end
  2940.  
  2941.  
  2942.  
  2943. class TrainerChecker
  2944.  def initialize
  2945.    @trainers=nil
  2946.    @trainertypes=nil
  2947.    @dontaskagain=false
  2948.  end
  2949.  
  2950.  def pbTrainerTypeCheck(symbol)
  2951.    ret=true
  2952.    if $DEBUG  
  2953.      return if @dontaskagain
  2954.      if !hasConst?(PBTrainers,symbol)
  2955.        ret=false
  2956.      else
  2957.        trtype=PBTrainers.const_get(symbol)
  2958.        @trainertypes=load_data("Data/trainertypes.dat") if !@trainertypes
  2959.        if !@trainertypes || !@trainertypes[trtype]    
  2960.          ret=false  
  2961.        end
  2962.      end  
  2963.      if !ret
  2964.        if Kernel.pbConfirmMessage(_INTL("Add new trainer named {1}?",symbol))
  2965.          pbTrainerTypeEditorNew(symbol.to_s)
  2966.          @trainers=nil
  2967.          @trainertypes=nil
  2968.        end
  2969. #        if pbMapInterpreter
  2970. #          pbMapInterpreter.command_end rescue nil
  2971. #        end
  2972.      end
  2973.    end
  2974.    return ret
  2975.  end
  2976.  
  2977.  def pbTrainerBattleCheck(trtype,trname,trid)
  2978.    if $DEBUG
  2979.      return if @dontaskagain
  2980.      if trtype.is_a?(String) || trtype.is_a?(Symbol)
  2981.        pbTrainerTypeCheck(trtype)
  2982.        return if !hasConst?(PBTrainers,trtype)
  2983.        trtype=PBTrainers.const_get(trtype)
  2984.      end
  2985.      @trainers=load_data("Data/trainers.dat") if !@trainers
  2986.      if @trainers
  2987.        for trainer in @trainers
  2988.          name=trainer[1]
  2989.          thistrainerid=trainer[0]
  2990.          thispartyid=trainer[4]
  2991.          next if name!=trname || thistrainerid!=trtype || thispartyid!=trid
  2992.          return
  2993.        end
  2994.      end
  2995.      cmd=pbMissingTrainer(trtype,trname,trid)
  2996.      if cmd==2
  2997.        @dontaskagain=true
  2998.        Graphics.update
  2999.      end
  3000.      @trainers=nil
  3001.      @trainertypes=nil
  3002.    end
  3003.  end
  3004. end
  3005.  
  3006.  
  3007.  
  3008. def pbCompileTrainerEvents(mustcompile)
  3009.  mapdata=MapData.new
  3010.  t = Time.now.to_i
  3011.  Graphics.update
  3012.  trainerChecker=TrainerChecker.new
  3013.  for id in mapdata.mapinfos.keys.sort
  3014.    changed=false
  3015.    map=mapdata.getMap(id)
  3016.    next if !map || !mapdata.mapinfos[id]
  3017.    Win32API.SetWindowText(_INTL("Processing map {1} ({2})",id,mapdata.mapinfos[id].name))
  3018.    for key in map.events.keys
  3019.      if Time.now.to_i - t >= 5
  3020.        Graphics.update
  3021.        t = Time.now.to_i
  3022.      end
  3023.      newevent=pbConvertToTrainerEvent(map.events[key],trainerChecker)
  3024.      if newevent
  3025.        changed=true
  3026.        map.events[key]=newevent
  3027.      end
  3028.      newevent=pbConvertToItemEvent(map.events[key])
  3029.      if newevent
  3030.        changed=true
  3031.        map.events[key]=newevent
  3032.      end
  3033.      newevent=pbFixEventUse(map.events[key],id,mapdata)
  3034.      if newevent
  3035.        changed=true
  3036.        map.events[key]=newevent
  3037.      end
  3038.    end
  3039.    if Time.now.to_i - t >= 5
  3040.      Graphics.update
  3041.      t = Time.now.to_i
  3042.    end
  3043.    changed=true if pbCheckCounters(map,id,mapdata)
  3044.    if changed
  3045.      mapdata.saveMap(id)
  3046.      mapdata.saveTilesets
  3047.    end
  3048.  end
  3049.  changed=false
  3050.  if Time.now.to_i-t>=5
  3051.    Graphics.update
  3052.    t=Time.now.to_i
  3053.  end
  3054.  commonEvents=pbLoadRxData("Data/CommonEvents")
  3055.  Win32API.SetWindowText(_INTL("Processing common events"))
  3056.  for key in 0...commonEvents.length
  3057.    newevent=pbFixEventUse(commonEvents[key],0,mapdata)
  3058.    if newevent
  3059.      changed=true
  3060.      map.events[key]=newevent
  3061.    end
  3062.  end
  3063.  if changed
  3064.    if $RPGVX
  3065.      save_data(commonEvents,"Data/CommonEvents.rvdata")
  3066.    else
  3067.      save_data(commonEvents,"Data/CommonEvents.rxdata")
  3068.    end
  3069.  end
  3070.  if !$RPGVX && $INTERNAL
  3071. #   convertVXProject(mapdata)
  3072.  end
  3073. end
  3074.  
  3075. def isPlainEvent?(event)
  3076.  return event && event.pages.length<=1 &&
  3077.         event.pages[0].list.length<=1 &&
  3078.         event.pages[0].move_type==0 &&
  3079.         event.pages[0].condition.switch1_valid==false &&
  3080.         event.pages[0].condition.switch2_valid==false &&
  3081.         event.pages[0].condition.variable_valid==false &&
  3082.         event.pages[0].condition.self_switch_valid==false
  3083. end
  3084.  
  3085. def isPlainEventOrMart?(event)
  3086.  return event &&
  3087.         event.pages.length<=1 &&
  3088.         event.pages[0].move_type==0 &&
  3089.         event.pages[0].condition.switch1_valid==false &&
  3090.         event.pages[0].condition.switch2_valid==false &&
  3091.         event.pages[0].condition.variable_valid==false &&
  3092.         event.pages[0].condition.self_switch_valid==false &&
  3093.         ((event.pages[0].list.length<=1) || (
  3094.         event.pages[0].list.length<=12 &&
  3095.         event.pages[0].graphic.character_name!="" &&
  3096.         event.pages[0].list[0].code==355 &&
  3097.         event.pages[0].list[0].parameters[0][/^pbPokemonMart/]) || (
  3098.         event.pages[0].list.length>8 &&
  3099.         event.pages[0].graphic.character_name!="" &&
  3100.         event.pages[0].list[0].code==355 &&
  3101.         event.pages[0].list[0].parameters[0][/^Kernel\.pbSetPokemonCenter/])
  3102.         )
  3103. end
  3104.  
  3105. def applyPages(page,pages)
  3106.  for p in pages
  3107.    p.graphic=page.graphic
  3108.    p.walk_anime=page.walk_anime
  3109.    p.step_anime=page.step_anime
  3110.    p.direction_fix=page.direction_fix
  3111.    p.through=page.through
  3112.    p.always_on_top=page.always_on_top
  3113.  end
  3114. end
  3115.  
  3116. def isLikelyCounter?(thisEvent,otherEvent,mapID,mapdata)
  3117.  # Check whether other event is likely on a counter tile
  3118.  yonderX=otherEvent.x+(otherEvent.x-thisEvent.x)
  3119.  yonderY=otherEvent.y+(otherEvent.y-thisEvent.y)
  3120.  return true if mapdata.isCounterTile?(mapID,otherEvent.x,otherEvent.y)
  3121.  return thisEvent.pages[0].graphic.character_name!="" &&
  3122.         otherEvent.pages[0].graphic.character_name=="" &&
  3123.         otherEvent.pages[0].trigger==0 &&
  3124.         mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
  3125.         !mapdata.isPassable?(mapID,otherEvent.x,otherEvent.y) &&
  3126.         mapdata.isPassable?(mapID,yonderX,yonderY)
  3127. end
  3128.  
  3129. def isLikelyPassage?(thisEvent,mapID,mapdata)
  3130.  return false if !thisEvent || thisEvent.pages.length==0
  3131.  return false if thisEvent.pages.length!=1
  3132.  if thisEvent.pages[0].graphic.character_name=="" &&
  3133.     thisEvent.pages[0].list.length<=12 &&
  3134.     thisEvent.pages[0].list.any? {|cmd| cmd.code==201 } &&
  3135. #     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y+1) &&
  3136.     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
  3137.     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y) &&
  3138.     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y) &&
  3139.     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y-1) &&
  3140.     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y-1)
  3141.    return true
  3142.  else
  3143.    return false
  3144.  end
  3145. end
  3146.  
  3147. def pbCheckCounters(map,mapID,mapdata)
  3148.  todelete=[]
  3149.  changed=false
  3150.  for key in map.events.keys
  3151.    event=map.events[key]
  3152.    next if !event
  3153.    firstCommand=event.pages[0].list[0]
  3154.    if isPlainEventOrMart?(event)
  3155.      # Empty event, check for counter events
  3156.      neighbors=[]
  3157.      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y-1))
  3158.      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y+1))
  3159.      neighbors.push(mapdata.getEventFromXY(mapID,event.x-1,event.y))
  3160.      neighbors.push(mapdata.getEventFromXY(mapID,event.x+1,event.y))
  3161.      neighbors.compact!
  3162.      for otherEvent in neighbors
  3163.        next if isPlainEvent?(otherEvent)
  3164.        if isLikelyCounter?(event,otherEvent,mapID,mapdata)
  3165.          mapdata.setCounterTile(mapID,otherEvent.x,otherEvent.y)
  3166.          savedPage=event.pages[0]
  3167.          event.pages=otherEvent.pages
  3168.          applyPages(savedPage,event.pages)
  3169.          todelete.push(otherEvent.id)
  3170.          changed=true
  3171.        end
  3172.      end
  3173.    end
  3174.  end
  3175.  for key in todelete
  3176.    map.events.delete(key)
  3177.  end
  3178.  return changed
  3179. end
  3180.  
  3181. def pbAddPassageList(event,mapdata)
  3182.  return if !event || event.pages.length==0
  3183.  page=RPG::Event::Page.new
  3184.  page.condition.switch1_valid=true
  3185.  page.condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3186.  page.graphic.character_name=""
  3187.  page.trigger=3 # Autorun
  3188.  page.list.clear
  3189.  list=page.list
  3190.  pbPushBranch(list,"get_character(0).onEvent?")
  3191.  pbPushEvent(list,208,[0],1)
  3192.  pbPushWait(list,6,1)
  3193.  pbPushEvent(list,208,[1],1)
  3194.  pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
  3195.  pbPushBranchEnd(list,1)
  3196.  pbPushScript(list,"setTempSwitchOn(\"A\")")
  3197.   pbPushEnd(list)
  3198.   event.pages.push(page)
  3199. end
  3200.  
  3201. def pbUpdateDoor(event,mapdata)
  3202.   changed=false
  3203.   return false if event.is_a?(RPG::CommonEvent)
  3204.   if event.pages.length>=2 &&
  3205.      event.pages[event.pages.length-1].condition.switch1_valid &&
  3206.      event.pages[event.pages.length-1].condition.switch1_id==12 &&
  3207.      event.pages[event.pages.length-1].list.length>5 &&
  3208.      event.pages[event.pages.length-1].graphic.character_name!="" &&
  3209.      mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
  3210.      event.pages[event.pages.length-1].list[0].code==111
  3211.     event.pages[event.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3212.     changed=true
  3213.   end
  3214.   if event.pages.length>=2 &&
  3215.      event.pages[event.pages.length-1].condition.switch1_valid &&
  3216.      event.pages[event.pages.length-1].list.length>5 &&
  3217.      event.pages[event.pages.length-1].graphic.character_name!="" &&
  3218.      mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)=='s:tsOff?("A")' &&
  3219.      event.pages[event.pages.length-1].list[0].code==111
  3220.     list=event.pages[event.pages.length-2].list
  3221.     transferCommand=list.find_all {|cmd| cmd.code==201 }
  3222.     if transferCommand.length==1 && !list.any?{|cmd| cmd.code==208 }
  3223.       list.clear
  3224.       pbPushMoveRouteAndWait(list,0,[
  3225.          PBMoveRoute::PlaySE,RPG::AudioFile.new("Entering Door"),PBMoveRoute::Wait,2,
  3226.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
  3227.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3228.          PBMoveRoute::TurnUp,PBMoveRoute::Wait,2])
  3229.       pbPushMoveRouteAndWait(list,-1,[
  3230.          PBMoveRoute::ThroughOn,PBMoveRoute::Up,PBMoveRoute::ThroughOff])
  3231.       pbPushEvent(list,208,[0]) # Change Transparent Flag
  3232.       pbPushMoveRouteAndWait(list,0,[PBMoveRoute::Wait,2,
  3233.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3234.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
  3235.          PBMoveRoute::TurnDown,PBMoveRoute::Wait,2])
  3236.       pbPushEvent(list,223,[Tone.new(-255,-255,-255),6])
  3237.       pbPushWait(list,8)
  3238.       pbPushEvent(list,208,[1])
  3239.       pbPushEvent(list,transferCommand[0].code,transferCommand[0].parameters)
  3240.       pbPushEvent(list,223,[Tone.new(0,0,0),6])
  3241.       pbPushEnd(list)
  3242.       list=event.pages[event.pages.length-1].list
  3243.       list.clear
  3244.       pbPushBranch(list,"get_character(0).onEvent?")
  3245.       pbPushEvent(list,208,[0],1)
  3246.       pbPushMoveRouteAndWait(list,0,[
  3247.          PBMoveRoute::TurnLeft,PBMoveRoute::Wait,6],1)
  3248.       pbPushEvent(list,208,[1],1)
  3249.       pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
  3250.       pbPushMoveRouteAndWait(list,0,[
  3251.          PBMoveRoute::TurnUp,PBMoveRoute::Wait,2,
  3252.          PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
  3253.          PBMoveRoute::TurnDown,PBMoveRoute::Wait,2],1)
  3254.       pbPushBranchEnd(list,1)
  3255.       pbPushScript(list,"setTempSwitchOn(\"A\")")
  3256.       pbPushEnd(list)
  3257.       changed=true
  3258.     end
  3259.   end
  3260.   return changed
  3261. end
  3262.  
  3263. def pbEventIsEmpty?(e)
  3264.   return true if !e
  3265.   if e.is_a?(RPG::CommonEvent)
  3266.     return false
  3267.   else
  3268.     return e.pages.length==0
  3269.   end
  3270. end
  3271.  
  3272. def pbEachPage(e)
  3273.   return true if !e
  3274.   if e.is_a?(RPG::CommonEvent)
  3275.     yield e
  3276.   else
  3277.     e.pages.each {|page| yield page }
  3278.   end
  3279. end
  3280.  
  3281. def pbChangeScript(script,re)
  3282.   tmp=script[0].gsub(re){ yield($~) }
  3283.   if script[0]!=tmp
  3284.     script[0]=tmp; return true
  3285.   end
  3286.   return false
  3287. end
  3288.  
  3289. def pbChangeScripts(script)
  3290.   changed=false
  3291.   changed|=pbChangeScript(script,/\$game_variables\[(\d+)\](?!\s*(?:\=|\!|<|>))/){|m| "pbGet("+m[1]+")" }
  3292.   changed|=pbChangeScript(script,/\$Trainer\.party\[\s*pbGet\((\d+)\)\s*\]/){|m| "pbGetPokemon("+m[1]+")" }
  3293.   return changed
  3294. end
  3295.  
  3296. def pbFixEventUse(event,mapID,mapdata)
  3297.   return nil if pbEventIsEmpty?(event)
  3298.   changed=false
  3299.   trainerMoneyRE=/^\s*\$Trainer\.money\s*(<|<=|>|>=)\s*(\d+)\s*$/
  3300.   itemBallRE=/^\s*(Kernel\.)?pbItemBall/
  3301.   if pbUpdateDoor(event,mapdata)
  3302.     changed=true
  3303.   end
  3304.   pbEachPage(event) do |page|
  3305.     i=0
  3306.     list=page.list
  3307.     while i<list.length
  3308.       params=list[i].parameters
  3309.       if list[i].code==655
  3310.         x=[params[0]]
  3311.         changed|=pbChangeScripts(x)
  3312.         params[0]=x[0]
  3313.       elsif list[i].code==355
  3314.         lastScript=i
  3315.         if !params[0].is_a?(String)
  3316.           i+=1
  3317.           next
  3318.         end
  3319.         x=[params[0]]
  3320.         changed|=pbChangeScripts(x)
  3321.         params[0]=x[0]
  3322.         if params[0][0,1]!="f" && params[0][0,1]!="p" && params[0][0,1]!="K"
  3323.           i+=1
  3324.           next
  3325.         end
  3326.         script=" "+params[0]
  3327.         j=i+1
  3328.         while j<list.length
  3329.           break if list[j].code!=655
  3330.           script+=list[j].parameters[0]
  3331.           lastScript=j
  3332.           j+=1
  3333.         end
  3334.         script.gsub!(/\s+/,"")
  3335.         # Using old method of recovering
  3336.         if script=="foriin$Trainer.partyi.healend"
  3337.           for j in i..lastScript
  3338.             list.delete_at(i)
  3339.           end
  3340.           list.insert(i,
  3341.              RPG::EventCommand.new(314,list[i].indent,[0]) # Recover All
  3342.           )
  3343.           changed=true
  3344.         elsif script=="pbFadeOutIn(99999){foriin$Trainer.partyi.healend}"
  3345.           oldIndent=list[i].indent
  3346.           for j in i..lastScript
  3347.             list.delete_at(i)
  3348.           end
  3349.           list.insert(i,
  3350.              RPG::EventCommand.new(223,oldIndent,[Tone.new(-255,-255,-255),6]), # Fade to black
  3351.              RPG::EventCommand.new(106,oldIndent,[6]), # Wait
  3352.              RPG::EventCommand.new(314,oldIndent,[0]), # Recover All
  3353.              RPG::EventCommand.new(223,oldIndent,[Tone.new(0,0,0),6]), # Fade to normal
  3354.              RPG::EventCommand.new(106,oldIndent,[6]) # Wait
  3355.           )
  3356.           changed=true
  3357.         end
  3358.       elsif list[i].code==108
  3359.         if params[0][/SellItem\s*\(\s*(\w+)\s*\,\s*(\d+)\s*\)/]
  3360.           itemname=$1
  3361.           cost=$2.to_i
  3362.           if hasConst?(PBItems,itemname)
  3363.             oldIndent=list[i].indent
  3364.             list.delete_at(i)
  3365.             newEvents=[]
  3366.             if cost==0
  3367.               pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent)
  3368.               pbPushText(newEvents,_INTL("Here you go!"),oldIndent+1)
  3369.               pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+1)
  3370.               pbPushElse(newEvents,oldIndent+1)
  3371.               pbPushText(newEvents,_INTL("You have no room left in the Bag."),oldIndent+1)
  3372.               pbPushBranchEnd(newEvents,oldIndent+1)
  3373.             else
  3374.               pbPushEvent(newEvents,111,[7,cost,0],oldIndent)
  3375.               pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent+1)
  3376.               pbPushEvent(newEvents,125,[1,0,cost],oldIndent+2)
  3377.               pbPushText(newEvents,_INTL("\\GHere you go!"),oldIndent+2)
  3378.               pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+2)
  3379.               pbPushElse(newEvents,oldIndent+2)
  3380.               pbPushText(newEvents,_INTL("\\GYou have no room left in the Bag."),oldIndent+2)
  3381.               pbPushBranchEnd(newEvents,oldIndent+2)
  3382.               pbPushElse(newEvents,oldIndent+1)
  3383.               pbPushText(newEvents,_INTL("\\GYou don't have enough money."),oldIndent+1)
  3384.               pbPushBranchEnd(newEvents,oldIndent+1)
  3385.             end
  3386.             list[i,0]=newEvents # insert 'newEvents' at index 'i'
  3387.             changed=true
  3388.           end
  3389.         end
  3390.       elsif list[i].code==115 && i==list.length-2
  3391.         # Superfluous exit command
  3392.         list.delete_at(i)
  3393.         changed=true
  3394.       elsif list[i].code==201 && list.length<=8
  3395.         if params[0]==0
  3396.           # Transfer back to door
  3397.           e=mapdata.getEventFromXY(params[1],params[2],params[3]-1)
  3398.           if e && e.pages.length>=2 &&
  3399.              e.pages[e.pages.length-1].condition.switch1_valid &&
  3400.              e.pages[e.pages.length-1].condition.switch1_id==12 &&
  3401.              mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
  3402.              e.pages[e.pages.length-1].list.length>5 &&
  3403.              e.pages[e.pages.length-1].list[0].code==111
  3404.             e.pages[e.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  3405.             mapdata.saveMap(params[1])
  3406.             changed=true
  3407.           end
  3408.           if isLikelyPassage?(e,params[1],mapdata)
  3409.             pbAddPassageList(e,mapdata)
  3410.             mapdata.saveMap(params[1])
  3411.             changed=true
  3412.           end
  3413.           if e && e.pages.length>=2 &&
  3414.              e.pages[e.pages.length-1].condition.switch1_valid &&
  3415.             mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)=='s:tsOff?("A")'
  3416.             # If this is really a door, move transfer target to it
  3417.             params[3]-=1
  3418.             params[5]=1 # No fade
  3419.             changed=true
  3420.           end
  3421.           deletedRoute=nil
  3422.           deleteMoveRouteAt=proc{|list,_i|
  3423.              arr=[]
  3424.              if list[_i] && list[_i].code==209
  3425.                arr.push(list[_i]);list.delete_at(_i)
  3426.                while _i<list.length
  3427.                  break if !list[_i] || list[_i].code!=509
  3428.                  arr.push(list[_i]);list.delete_at(_i)    
  3429.                end
  3430.              end
  3431.              next arr
  3432.           }
  3433.           insertMoveRouteAt=proc{|list,_i,route|
  3434.              _j=route.length-1
  3435.              while _j>=0
  3436.                list.insert(_i,route[_j])
  3437.                _j-=1
  3438.              end
  3439.           }
  3440.           if params[4]==0 && # Retain direction
  3441.              i+1<list.length && list[i+1].code==209 && list[i+1].parameters[0]==-1
  3442.             route=list[i+1].parameters[1]
  3443.             if route && route.list.length<=2
  3444.               # Delete superfluous move route command if necessary
  3445.               if route.list[0].code==16 # Player/Turn Down
  3446.                 deleteMoveRouteAt.call(list,i+1); params[4]=2; changed=true
  3447.               elsif route.list[0].code==17 # Left
  3448.                 deleteMoveRouteAt.call(list,i+1); params[4]=4; changed=true
  3449.               elsif route.list[0].code==18 # Right
  3450.                 deleteMoveRouteAt.call(list,i+1); params[4]=6; changed=true
  3451.               elsif route.list[0].code==19 # Up
  3452.                 deleteMoveRouteAt.call(list,i+1); params[4]=8; changed=true
  3453.               elsif (route.list[0].code==1 || route.list[0].code==2 ||
  3454.                  route.list[0].code==3 || route.list[0].code==4) && list.length==4
  3455.                 params[4]=[0,2,4,6,8][route.list[0].code]
  3456.                 deletedRoute=deleteMoveRouteAt.call(list,i+1); changed=true
  3457.               end
  3458.             end
  3459.           elsif params[4]==0 && i>3
  3460.             for j in 0...i
  3461.               if list[j].code==209 && list[j].parameters[0]==-1
  3462.                 route=list[j].parameters[1]
  3463.                 oldlistlength=list.length
  3464.                 if route && route.list.length<=2
  3465.                   # Delete superfluous move route command if necessary
  3466.                   if route.list[0].code==16 # Player/Turn Down
  3467.                     deleteMoveRouteAt.call(list,j); params[4]=2; changed=true;i-=(oldlistlength-list.length)
  3468.                   elsif route.list[0].code==17 # Left
  3469.                     deleteMoveRouteAt.call(list,j); params[4]=4; changed=true;i-=(oldlistlength-list.length)
  3470.                   elsif route.list[0].code==18 # Right
  3471.                     deleteMoveRouteAt.call(list,j); params[4]=6; changed=true;i-=(oldlistlength-list.length)
  3472.                   elsif route.list[0].code==19 # Up
  3473.                     deleteMoveRouteAt.call(list,j); params[4]=8; changed=true;i-=(oldlistlength-list.length)
  3474.                   end
  3475.                 end
  3476.               end
  3477.             end
  3478.           elsif params[4]==0 && # Retain direction
  3479.              i+2<list.length &&
  3480.              list[i+1].code==223 &&
  3481.              list[i+2].code==209 &&
  3482.              list[i+2].parameters[0]==-1
  3483.             route=list[i+2].parameters[1]
  3484.             if route && route.list.length<=2
  3485.               # Delete superfluous move route command if necessary
  3486.               if route.list[0].code==16 # Player/Turn Down
  3487.                 deleteMoveRouteAt.call(list,i+2); params[4]=2; changed=true
  3488.               elsif route.list[0].code==17 # Left
  3489.                 deleteMoveRouteAt.call(list,i+2); params[4]=4; changed=true
  3490.               elsif route.list[0].code==18 # Right
  3491.                 deleteMoveRouteAt.call(list,i+2); params[4]=6; changed=true
  3492.               elsif route.list[0].code==19 # Up
  3493.                 deleteMoveRouteAt.call(list,i+2); params[4]=8; changed=true
  3494.               end
  3495.             end
  3496.           end
  3497.         end
  3498.         # If this is the only event command, convert to a full event
  3499.         if list.length==2 || (list.length==3 && (list[0].code==250 || list[1].code==250))
  3500.           params[5]=1 # No fade
  3501.           fullTransfer=list[i]
  3502.           indent=list[i].indent
  3503.           (list.length-1).times { list.delete_at(0) }
  3504.           list.insert(0,
  3505.              RPG::EventCommand.new(250,indent,[RPG::AudioFile.new("Exit Door",80,100)]), # Play SE
  3506.              RPG::EventCommand.new(223,indent,[Tone.new(-255,-255,-255),6]), # Fade to black
  3507.              RPG::EventCommand.new(106,indent,[8]), # Wait
  3508.              fullTransfer, # Transfer event
  3509.              RPG::EventCommand.new(223,indent,[Tone.new(0,0,0),6]) # Fade to normal
  3510.           )
  3511.           changed=true
  3512.         end
  3513.         if deletedRoute
  3514.           insertMoveRouteAt.call(list,list.length-1,deletedRoute)
  3515.           changed=true
  3516.         end
  3517.       elsif list[i].code==101
  3518.         if list[i].parameters[0][0,1]=="\\"
  3519.           newx=list[i].parameters[0].clone
  3520.           newx.sub!(/^\\[Bb]\s+/,"\\b")
  3521.           newx.sub!(/^\\[Rr]\s+/,"\\r")
  3522.           newx.sub!(/^\\[Pp][Gg]\s+/,"\\pg")
  3523.           newx.sub!(/^\\[Pp][Oo][Gg]\s+/,"\\pog")
  3524.           newx.sub!(/^\\[Gg]\s+/,"\\G")
  3525.           newx.sub!(/^\\[Cc][Nn]\s+/,"\\CN")
  3526.           if list[i].parameters[0]!=newx
  3527.             list[i].parameters[0]=newx
  3528.             changed=true
  3529.           end
  3530.         end
  3531.         lines=1
  3532.         j=i+1; while j<list.length
  3533.           break if list[j].code!=401
  3534.           if lines%4==0
  3535.             list[j].code=101
  3536.             changed=true
  3537.           end
  3538.           lines+=1
  3539.           j+=1
  3540.         end
  3541.         if lines>=2 && list[i].parameters[0].length>0 && list[i].parameters[0].length<=20 &&
  3542.            !list[i].parameters[0][/\\n/]
  3543.           # Very short line
  3544.           list[i].parameters[0]+="\\n"+list[i+1].parameters[0]
  3545.           list.delete_at(i+1)
  3546.           i-=1 # revisit this text command
  3547.           changed=true
  3548.         elsif lines>=3 && list[i+lines] && list[i+lines].code==101
  3549.           # Check whether a sentence is being broken midway
  3550.           # between two Text commands
  3551.           lastLine=list[i+lines-1].parameters[0].sub(/\s+$/,"")
  3552.           if lastLine.length>0 && !lastLine[/[\\<]/] && lastLine[/[^\.,\!\?\;\-\"]$/]
  3553.            message=list[i].parameters[0]
  3554.            j=i+1; while j<list.length
  3555.              break if list[j].code!=401
  3556.              message+="\n"+list[j].parameters[0]
  3557.              j+=1
  3558.            end
  3559.            punct=[message.rindex(". "),message.rindex(".\n"),
  3560.               message.rindex("!"),message.rindex("?"),-1].compact.max
  3561.            if punct==-1
  3562.              punct=[message.rindex(", "),message.rindex(",\n"),-1].compact.max
  3563.            end
  3564.            if punct!=-1
  3565.              # Delete old message
  3566.              indent=list[i].indent
  3567.              newMessage=message[0,punct+1].split("\n")
  3568.              nextMessage=message[punct+1,message.length].sub(/^\s+/,"").split("\n")
  3569.              list[i+lines].code=401
  3570.              lines.times { list.delete_at(i) }
  3571.              j=nextMessage.length-1;while j>=0
  3572.                list.insert(i,RPG::EventCommand.new(
  3573.                j==0 ? 101 : 401,indent,[nextMessage[j]]))
  3574.                j-=1
  3575.              end
  3576.              j=newMessage.length-1;while j>=0
  3577.                list.insert(i,RPG::EventCommand.new(
  3578.                j==0 ? 101 : 401,indent,[newMessage[j]]))
  3579.                j-=1
  3580.              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\:|Outcome\:)/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.   outcome=0
  3753.   for command in commands
  3754.     if command[/^Battle\:\s*([\s\S]+)$/i]
  3755.       battles.push($~[1])
  3756.       pbPushComment(firstpage.list,command)
  3757.     end
  3758.     if command[/^Type\:\s*([\s\S]+)$/i]
  3759.       trtype=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3760.       pbPushComment(firstpage.list,command)
  3761.     end
  3762.     if command[/^Name\:\s*([\s\S]+)$/i]
  3763.       trname=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3764.       pbPushComment(firstpage.list,command)
  3765.     end
  3766.     if command[/^EndSpeech\:\s*([\s\S]+)$/i]
  3767.       endspeeches.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
  3768.       pbPushComment(firstpage.list,command)
  3769.     end
  3770.     if command[/^EndIfSwitch\:\s*([\s\S]+)$/i]
  3771.       endifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
  3772.       pbPushComment(firstpage.list,command)
  3773.     end
  3774.     if command[/^DoubleBattle\:\s*([\s\S]+)$/i]
  3775.       value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3776.       doublebattle=true if value.upcase=="TRUE" || value.upcase=="YES"
  3777.       pbPushComment(firstpage.list,command)
  3778.     end
  3779.     if command[/^VanishIfSwitch\:\s*([\s\S]+)$/i]
  3780.       vanishifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
  3781.       pbPushComment(firstpage.list,command)
  3782.     end
  3783.     if command[/^Backdrop\:\s*([\s\S]+)$/i]
  3784.       backdrop=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3785.       pbPushComment(firstpage.list,command)
  3786.     end
  3787.     if command[/^RegSpeech\:\s*([\s\S]+)$/i]
  3788.       regspeech=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3789.       pbPushComment(firstpage.list,command)
  3790.     end
  3791.     if command[/^EndBattle\:\s*([\s\S]+)$/i]
  3792.       endbattles.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
  3793.       pbPushComment(firstpage.list,command)
  3794.     end
  3795.     if command[/^BattleID\:\s*(\d+)$/i]
  3796.       battleid=$~[1].to_i
  3797.       pbPushComment(firstpage.list,command)
  3798.     end
  3799.     if command[/^Continue\:\s*([\s\S]+)$/i]
  3800.       value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
  3801.       continue=true if value.upcase=="TRUE" || value.upcase=="YES"
  3802.       pbPushComment(firstpage.list,command)
  3803.     end
  3804.     if command[/^Outcome\:\s*(\d+)$/i]
  3805.       outcome=$~[1].to_i
  3806.       pbPushComment(firstpage.list,command)
  3807.     end
  3808.   end
  3809.   if battles.length<=0
  3810.     return nil
  3811.   end
  3812.   if firstpage.graphic.character_name=="" && hasConst?(PBTrainers,trtype)
  3813.     trainerid=getConst(PBTrainers,trtype)
  3814.     if trainerid
  3815.       filename=pbTrainerCharNameFile(trainerid)
  3816.       if FileTest.image_exist?("Graphics/Characters/"+filename)
  3817.         firstpage.graphic.character_name=sprintf(filename)
  3818.       end
  3819.     end
  3820.   end
  3821.   safetrcombo=sprintf("PBTrainers:"+":%s,\"%s\"",trtype,safequote(trname))
  3822.   safetrcombo2=sprintf(":%s,\"%s\"",trtype,safequote(trname))
  3823.   introplay=sprintf("pbTrainerIntro(:%s)",trtype)
  3824.   pbPushScript(firstpage.list,introplay)
  3825.   pbPushScript(firstpage.list,"Kernel.pbNoticePlayer(get_character(0))")
  3826.   pbPushText(firstpage.list,battles[0])
  3827.   if battles.length>1
  3828.     pbPushScript(firstpage.list,sprintf("Kernel.pbTrainerCheck(%s,%d,%d)",safetrcombo2,battles.length,battleid))
  3829.   end
  3830.   if backdrop
  3831.     pbPushScript(firstpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)))
  3832.   end
  3833.   espeech=(endspeeches[0]) ? endspeeches[0] : "..."
  3834.   # Run trainer check now, except in editor
  3835.   trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid) if !$INEDITOR
  3836.   pbPushBranch(firstpage.list,
  3837.      sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s,%d)",
  3838.      safetrcombo,safequote2(espeech),
  3839.      doublebattle ? "true" : "false",
  3840.      battleid,
  3841.      continue ? "true" : "false",
  3842.      outcome)
  3843.   )
  3844.   if battles.length>1
  3845.     pbPushScript(firstpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  3846.   end
  3847.   pbPushSelfSwitch(firstpage.list,"A",true,1)
  3848.   pbPushBranchEnd(firstpage.list,1)
  3849.   pbPushScript(firstpage.list,"pbTrainerEnd",0)
  3850.   pbPushEnd(firstpage.list)
  3851.   secondpage=Marshal::load(Marshal.dump(firstpage))
  3852.   secondpage.list=[]
  3853.   secondpage.trigger=0
  3854.   secondpage.condition=firstpage.condition.clone
  3855.   thirdpage=Marshal::load(Marshal.dump(secondpage))
  3856.   thirdpage.list=secondpage.list.clone
  3857.   thirdpage.condition=secondpage.condition.clone
  3858.   secondpage.condition.self_switch_valid=true
  3859.   secondpage.condition.self_switch_ch="A"
  3860.   thirdpage.condition.self_switch_valid=true
  3861.   thirdpage.condition.self_switch_ch="B"
  3862.   for i in 1...battles.length
  3863.     if endspeeches.length==0
  3864.       espeech="..."
  3865.     else
  3866.       espeech=(endspeeches[i]) ? endspeeches[i] : endspeeches[endspeeches.length-1]
  3867.     end
  3868.     if endbattles.length==0
  3869.       ebattle=nil
  3870.     else
  3871.       ebattle=(endbattles[i]) ? endbattles[i] : endbattles[endbattles.length-1]
  3872.     end
  3873.     if i==battles.length-1
  3874.       pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)>=%d",safetrcombo,i))
  3875.       pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)>%d",safetrcombo,i))
  3876.     else
  3877.       pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
  3878.       pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
  3879.     end
  3880.     pbPushText(secondpage.list,ebattle,1)
  3881.     pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  3882.     pbPushExit(secondpage.list,1)
  3883.     pbPushBranchEnd(secondpage.list,1)
  3884.     pbPushScript(thirdpage.list,introplay,1)
  3885.     pbPushText(thirdpage.list,battles[i],1)
  3886.     # Run trainer check now, except in editor
  3887.     trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid+i) if !$INEDITOR
  3888.     if backdrop
  3889.       pbPushScript(thirdpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)),1)
  3890.     end
  3891.     pbPushBranch(thirdpage.list,
  3892.        sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s,%d)",
  3893.        safetrcombo,safequote2(espeech),
  3894.        doublebattle ? "true" : "false",
  3895.        battleid+i,
  3896.        continue ? "true" : "false",
  3897.        outcome),1
  3898.     )
  3899.     pbPushScript(thirdpage.list,
  3900.        sprintf("pbPhoneIncrement(%s,%d)",safetrcombo,battles.length),2)
  3901.     pbPushSelfSwitch(thirdpage.list,"A",true,2)
  3902.     pbPushSelfSwitch(thirdpage.list,"B",false,2)
  3903.     pbPushScript(thirdpage.list,"pbTrainerEnd",2)
  3904.     pbPushBranchEnd(thirdpage.list,2)
  3905.     pbPushExit(thirdpage.list,1)
  3906.     pbPushBranchEnd(thirdpage.list,1)
  3907.   end
  3908.   ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3909.   pbPushText(secondpage.list,ebattle)
  3910.   if battles.length>1
  3911.     pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length))
  3912.   end
  3913.   pbPushEnd(secondpage.list)
  3914.   pbPushEnd(thirdpage.list)
  3915.   if battles.length==1
  3916.     ret.pages=[firstpage,secondpage]
  3917.   else
  3918.     ret.pages=[firstpage,thirdpage,secondpage]
  3919.   end
  3920.   for endswitch in endifswitch
  3921.     ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3922.     endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
  3923.     endIfSwitchPage.condition=secondpage.condition.clone
  3924.     if endIfSwitchPage.condition.switch1_valid
  3925.       endIfSwitchPage.condition.switch2_valid=true
  3926.       endIfSwitchPage.condition.switch2_id=endswitch
  3927.     else
  3928.       endIfSwitchPage.condition.switch1_valid=true
  3929.       endIfSwitchPage.condition.switch1_id=endswitch
  3930.     end
  3931.     endIfSwitchPage.condition.self_switch_valid=false
  3932.     endIfSwitchPage.list=[]
  3933.     pbPushText(endIfSwitchPage.list,ebattle)
  3934.     pbPushEnd(endIfSwitchPage.list)
  3935.     ret.pages.push(endIfSwitchPage)
  3936.   end
  3937.   for endswitch in vanishifswitch
  3938.     ebattle=(endbattles[0]) ? endbattles[0] : "..."
  3939.     endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
  3940.     endIfSwitchPage.graphic.character_name="" # make blank
  3941.     endIfSwitchPage.condition=secondpage.condition.clone
  3942.     if endIfSwitchPage.condition.switch1_valid
  3943.       endIfSwitchPage.condition.switch2_valid=true
  3944.       endIfSwitchPage.condition.switch2_id=endswitch
  3945.     else
  3946.       endIfSwitchPage.condition.switch1_valid=true
  3947.       endIfSwitchPage.condition.switch1_id=endswitch
  3948.     end
  3949.     endIfSwitchPage.condition.self_switch_valid=false
  3950.     endIfSwitchPage.list=[]
  3951.     pbPushEnd(endIfSwitchPage.list)
  3952.     ret.pages.push(endIfSwitchPage)
  3953.   end
  3954.   return ret
  3955. end
  3956.  
  3957. def pbCompileAnimations
  3958.   begin
  3959.     if $RPGVX
  3960.       pbanims=load_data("Data/PkmnAnimations.rvdata")
  3961.     else
  3962.       pbanims=load_data("Data/PkmnAnimations.rxdata")
  3963.     end
  3964.   rescue
  3965.     pbanims=PBAnimations.new
  3966.   end
  3967.   move2anim=[[],[]]
  3968. =begin
  3969.   if $RPGVX
  3970.     anims=load_data("Data/Animations.rvdata")
  3971.   else
  3972.     anims=load_data("Data/Animations.rxdata")
  3973.   end
  3974.   for anim in anims
  3975.     next if !anim || anim.frames.length==1
  3976.     found=false
  3977.     for i in 0...pbanims.length
  3978.       if pbanims[i] && pbanims[i].id==anim.id
  3979.         found=true if pbanims[i].array.length>1
  3980.         break
  3981.       end
  3982.     end
  3983.     if !found
  3984.       pbanims[anim.id]=pbConvertRPGAnimation(anim)
  3985.     end
  3986.   end
  3987. =end
  3988.   for i in 0...pbanims.length
  3989.     next if !pbanims[i]
  3990.     if pbanims[i].name[/^OppMove\:\s*(.*)$/]
  3991.       if Kernel.hasConst?(PBMoves,$~[1])
  3992.         moveid=PBMoves.const_get($~[1])
  3993.         move2anim[1][moveid]=i
  3994.       end
  3995.     elsif pbanims[i].name[/^Move\:\s*(.*)$/]
  3996.       if Kernel.hasConst?(PBMoves,$~[1])
  3997.         moveid=PBMoves.const_get($~[1])
  3998.         move2anim[0][moveid]=i
  3999.       end
  4000.     end
  4001.   end
  4002.   save_data(move2anim,"Data/move2anim.dat")
  4003.   save_data(pbanims,"Data/PkmnAnimations.rxdata")
  4004. end
  4005.  
  4006. def pbCompileAllData(mustcompile)
  4007.   FileLineData.clear
  4008.   if mustcompile
  4009.     if (!$INEDITOR || LANGUAGES.length<2) && pbRgssExists?("Data/messages.dat")
  4010.       MessageTypes.loadMessageFile("Data/messages.dat")
  4011.     end
  4012.     # No dependencies
  4013.     yield(_INTL("Compiling type data"))
  4014.     pbCompileTypes
  4015.     # No dependencies
  4016.     yield(_INTL("Compiling town map data"))
  4017.     pbCompileTownMap
  4018.     # No dependencies
  4019.     yield(_INTL("Compiling map connection data"))
  4020.     pbCompileConnections
  4021.     # No dependencies  
  4022.     yield(_INTL("Compiling ability data"))
  4023.     pbCompileAbilities
  4024.     # Depends on PBTypes
  4025.     yield(_INTL("Compiling move data"))
  4026.     pbCompileMoves
  4027.     # Depends on PBMoves
  4028.     yield(_INTL("Compiling item data"))
  4029.     pbCompileItems
  4030.     # Depends on PBMoves, PBItems, PBTypes, PBAbilities
  4031.     yield(_INTL("Compiling Pokemon data"))
  4032.     pbCompilePokemonData
  4033.     # Depends on PBSpecies, PBMoves
  4034.     yield(_INTL("Compiling machine data"))
  4035.     pbCompileMachines
  4036.     # Depends on PBSpecies, PBItems, PBMoves
  4037.     yield(_INTL("Compiling Trainer data"))
  4038.     pbCompileTrainers
  4039.     # Depends on PBTrainers
  4040.     yield(_INTL("Compiling phone data"))
  4041.     pbCompilePhoneData
  4042.     # Depends on PBTrainers
  4043.     yield(_INTL("Compiling metadata"))
  4044.     pbCompileMetadata
  4045.     # Depends on PBTrainers
  4046.     yield(_INTL("Compiling battle Trainer data"))
  4047.     pbCompileTrainerLists
  4048.     # Depends on PBSpecies
  4049.     yield(_INTL("Compiling encounter data"))
  4050.     pbCompileEncounters
  4051.     # Depends on PBSpecies, PBMoves
  4052.     yield(_INTL("Compiling shadow move data"))
  4053.     pbCompileShadowMoves
  4054.     yield(_INTL("Compiling messages"))
  4055.   else
  4056.     if (!$INEDITOR || LANGUAGES.length<2) && safeExists?("Data/messages.dat")
  4057.       MessageTypes.loadMessageFile("Data/messages.dat")
  4058.     end
  4059.   end
  4060.   pbCompileAnimations
  4061.   pbCompileTrainerEvents(mustcompile)
  4062.   pbSetTextMessages
  4063.   MessageTypes.saveMessages
  4064.   if !$INEDITOR && LANGUAGES.length>=2
  4065.     pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
  4066.   end
  4067. end
  4068.  
  4069. def pbImportNewMaps
  4070.   return false if !$DEBUG
  4071.   mapfiles={}
  4072.   # Get IDs of all maps in the Data folder
  4073.   Dir.chdir("Data"){
  4074.      mapdata=sprintf("Map*.%s","rxdata",$RPGVX ? "rvdata" : "rxdata")
  4075.      for map in Dir.glob(mapdata)
  4076.        if map[/map(\d+)\.rxdata/i]
  4077.          mapfiles[$1.to_i(10)]=true
  4078.        end
  4079.      end
  4080.   }
  4081.   mapinfos=pbLoadRxData("Data/MapInfos")
  4082.   maxOrder=0
  4083.   # Exclude maps found in mapinfos
  4084.   for id in mapinfos.keys
  4085.     next if !mapinfos.id
  4086.     if mapfiles[id]
  4087.       mapfiles.delete(id)
  4088.     end
  4089.     maxOrder=[maxOrder,mapinfos[id].order].max
  4090.   end
  4091.   # Import maps not found in mapinfos
  4092.   maxOrder+=1
  4093.   imported=false
  4094.   for id in mapfiles.keys
  4095.     next if id==999 # Ignore 999 (random dungeon map)
  4096.     mapname=sprintf("MAP%03d",id)
  4097.     mapinfo=RPG::MapInfo.new
  4098.     mapinfo.order=maxOrder
  4099.     maxOrder+=1
  4100.     mapinfo.name=mapname
  4101.     mapinfos[id]=mapinfo
  4102.     imported=true
  4103.   end
  4104.   if imported
  4105.     if $RPGVX
  4106.       save_data(mapinfos,"Data/MapInfos.rvdata")
  4107.     else
  4108.       save_data(mapinfos,"Data/MapInfos.rxdata")
  4109.     end
  4110.     Kernel.pbMessage(_INTL("New maps copied to the Data folder were successfully imported.",id))
  4111.   end
  4112.   return imported
  4113. end
  4114.  
  4115. if $DEBUG
  4116.   latestdatatime=0
  4117.   latesttexttime=0
  4118.   mustcompile=false
  4119.   mustcompile|=pbImportNewMaps
  4120.   mustcompile|=!(PBSpecies.respond_to?("maxValue") rescue false)
  4121.   if !safeIsDirectory?("PBS")
  4122.     Dir.mkdir("PBS") rescue nil
  4123.     pbSaveAllData()
  4124.     mustcompile=true
  4125.   end
  4126.   for i in 0...datafiles.length
  4127.     begin
  4128.       File.open("Data/#{datafiles[i]}"){|file|
  4129.          latestdatatime=[latestdatatime,file.mtime.to_i].max
  4130.       }
  4131.     rescue SystemCallError
  4132.       mustcompile=true
  4133.     end
  4134.   end
  4135.   for i in 0...textfiles.length
  4136.     begin
  4137.       File.open("PBS/#{textfiles[i]}"){|file|
  4138.          latesttexttime=[latesttexttime,file.mtime.to_i].max
  4139.       }
  4140.     rescue SystemCallError
  4141.     end
  4142.   end
  4143.   mustcompile=mustcompile || (latesttexttime>=latestdatatime)
  4144.   Input.update
  4145.   if Input.press?(Input::CTRL)
  4146.     mustcompile=true
  4147.   end
  4148.   if mustcompile
  4149.     for i in 0...datafiles.length
  4150.       begin
  4151.         File.delete("Data/#{datafiles[i]}")
  4152.       rescue SystemCallError
  4153.       end
  4154.     end
  4155.   end
  4156.   pbCompileAllData(mustcompile){|msg| Win32API.SetWindowText(msg) }
  4157. end
  4158.  
  4159.  
  4160.  
  4161. rescue Exception
  4162.   e=$!
  4163.   if "#{e.class}"=="Reset" || e.is_a?(Reset) || e.is_a?(SystemExit)
  4164.     raise e
  4165.   end
  4166.   pbPrintException(e)
  4167.   for i in 0...datafiles.length
  4168.     begin
  4169.       File.delete("Data/#{datafiles[i]}")
  4170.     rescue SystemCallError
  4171.     end
  4172.   end
  4173.   if e.is_a?(Hangup)
  4174.     raise Reset.new
  4175.   end
  4176.   loop do
  4177.     Graphics.update
  4178.   end
  4179. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement