• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Pokemon Contests Script 1.5

mewlover22

Pokemon Creator
455
Posts
15
Years
Tired your fix in a clean version and i got this error did i forget something because i did everything in the post you told me to do.

---------------------------
Pokemon Essentials
---------------------------
Exception: RuntimeError

Message: Script error within event 21, map 22 (Contest Hall):

Exception: NoMethodError

Message: Section177:154:in `pbTurn'undefined method `pbCustomMessage' for Kernel:Module

***Full script:

Kernel.pbMessage(_INTL("First up is Gary's Butterscortch!"))
showSpeciesIntro(PBSpecies::CHARIZARD,"","Butterscortch")
pbAddContestMove(2,1,2,3,7)
pbChangeContestName(2,"Butterscortch")
pbContest(50,PBSpecies::CHARIZARD,20,PBSpecies::SQUIRTLE,20,PBSpecies::HITMONTOP,20,1)


Interpreter:243:in `pbExecuteScript'

Contest:115:in `pbStartContest'

Contest:2460:in `pbStartContest'

Contest:2470:in `pbContest'

(eval):5:in `pbExecuteScript'

Interpreter:1606:in `eval'

Interpreter:243:in `pbExecuteScript'

Interpreter:1606:in `command_355'

Interpreter:494:in `execute_command'

Interpreter:193:in `update'



Interpreter:276:in `pbExecuteScript'

Interpreter:1606:in `command_355'

Interpreter:494:in `execute_command'

Interpreter:193:in `update'

Interpreter:106:in `loop'

Interpreter:198:in `update'

Scene_Map:103:in `update'

Scene_Map:101:in `loop'

Scene_Map:114:in `update'

Scene_Map:68:in `main'



This exception was logged in

C:\Users\Chris\Saved Games/Pokemon Essentials/errorlog.txt.

Press Ctrl+C to copy this message to the clipboard.
---------------------------
OK
---------------------------
 
31
Posts
8
Years
Well from what I can see the problem is in pbCustomMessage and that should be where the trouble is...
All I needed to do in v16.1 was just add in Messages
Above def Kernel.pbMessage around line 996

Code:
def Kernel.pbCustomMessage(message,skin=nil,newx=nil,newwidth=nil,&block) ret=0 msgwindow=Kernel.pbCreateMessageWindow(nil,skin) msgwindow.x=newx if newx!=nil if newwidth!=nil msgwindow.width=newwidth else msgwindow.width=Graphics.width-msgwindow.x end Kernel.pbMessageDisplay(msgwindow,message,&block) Kernel.pbDisposeMessageWindow(msgwindow) Input.update return ret end

And I skipped the second part of that because it really isn't needed.

Because in the Main Contest script under
def pbTurn(turnnumber)
it uses the pbCustomMessage
and I know changing that part of the script isn't what is needed.
 
Last edited:

mewlover22

Pokemon Creator
455
Posts
15
Years
Well from what I can see the problem is in pbCustomMessage and that should be where the trouble is...
All I needed to do in v16.1 was just add in Messages
Code:
def Kernel.pbCustomMessage(message,skin=nil,newx=nil,newwidth=nil,&block) ret=0 msgwindow=Kernel.pbCreateMessageWindow(nil,skin) msgwindow.x=newx if newx!=nil if newwidth!=nil msgwindow.width=newwidth else msgwindow.width=Graphics.width-msgwindow.x end Kernel.pbMessageDisplay(msgwindow,message,&block) Kernel.pbDisposeMessageWindow(msgwindow) Input.update return ret end



And I skipped the second part of that because it really isn't needed.

Where do these go in the main script?
 
31
Posts
8
Years
Ok Here is my Messages Script
Code:
class Game_Temp
  attr_writer :message_window_showing
  attr_writer :player_transferring
  attr_writer :transition_processing

  def message_window_showing
    @message_window_showing=false if !@message_window_showing
    return @message_window_showing
  end

  def player_transferring
    @player_transferring=false if !@player_transferring
    return @player_transferring
  end

  def transition_processing
    @transition_processing=false if !@transition_processing
    return @transition_processing
  end
end



class Game_Message
  attr_writer :background, :visible
  def visible; return @visible ? @visible : false; end
  def background; return @background ? @background : 0; end
end



class Game_System
  attr_writer :message_position

  def message_position
    @message_position=2 if !@message_position
    return @message_position
  end
end



#########

class Scene_Map
  def updatemini
    oldmws=$game_temp.message_window_showing
    oldvis=$game_message ? $game_message.visible : false
    $game_temp.message_window_showing=true
    $game_message.visible=true if $game_message
    loop do
      $game_map.update
      $game_player.update
      $game_system.update
      if $game_screen
        $game_screen.update
      else
        $game_map.screen.update
      end
      unless $game_temp.player_transferring
        break
      end
      transfer_player
      if $game_temp.transition_processing
        break
      end
    end
    $game_temp.message_window_showing=oldmws
    $game_message.visible=oldvis if $game_message
    @spriteset.update if @spriteset
    @message_window.update if @message_window
  end
end



class Scene_Battle
  def updatemini
    if self.respond_to?("update_basic")
      update_basic(true)
      update_info_viewport                  # Update information viewport
      if $game_message && $game_message.visible
        @info_viewport.visible = false
        @message_window.visible = true
      end
    else
      oldmws=$game_temp.message_window_showing
      $game_temp.message_window_showing=true
      # Update system (timer) and screen
      $game_system.update
      if $game_screen
        $game_screen.update
      else
        $game_map.screen.update
      end    
      # If timer has reached 0
      if $game_system.timer_working and $game_system.timer == 0
        # Abort battle
        $game_temp.battle_abort = true
      end
      # Update windows
      @help_window.update if @help_window
      @party_command_window.update if @party_command_window
      @actor_command_window.update if @actor_command_window
      @status_window.update if @status_window
      $game_temp.message_window_showing=oldmws
      @message_window.update if @message_window
      # Update sprite set
      @spriteset.update if @spriteset
    end
  end
end



def pbMapInterpreterRunning?
  interp=pbMapInterpreter
  return interp && interp.running?
end

def pbMapInterpreter
  if $game_map && $game_map.respond_to?("interpreter")
    return $game_map.interpreter
  elsif $game_system
    return $game_system.map_interpreter
  end
  return nil
end

def pbRefreshSceneMap
  if $scene && $scene.is_a?(Scene_Map)
    if $scene.respond_to?("miniupdate")
      $scene.miniupdate
    else
      $scene.updatemini
    end
  elsif $scene && $scene.is_a?(Scene_Battle)
    $scene.updatemini
  end
end

def pbUpdateSceneMap
  if $scene && $scene.is_a?(Scene_Map) && !pbIsFaded?
    if $scene.respond_to?("miniupdate")
      $scene.miniupdate
    else
      $scene.updatemini
    end
  elsif $scene && $scene.is_a?(Scene_Battle)
    $scene.updatemini
  end
end
#########

def pbCsvField!(str)
  ret=""
  str.sub!(/\A\s*/,"")
  if str[0,1]=="\""
    str[0,1]=""
    escaped=false
    fieldbytes=0
    str.scan(/./) do |s|
      fieldbytes+=s.length
      break if s=="\"" && !escaped
      if s=="\\" && !escaped
        escaped=true
      else
        ret+=s
        escaped=false
      end
    end
    str[0,fieldbytes]=""
    if !str[/\A\s*,/] && !str[/\A\s*$/] 
      raise _INTL("Invalid quoted field (in: {1})",ret)
    end
    str[0,str.length]=$~.post_match
  else
    if str[/,/]
      str[0,str.length]=$~.post_match
      ret=$~.pre_match
    else
      ret=str.clone
      str[0,str.length]=""
    end
    ret.gsub!(/\s+$/,"")
  end
  return ret
end

def pbCsvPosInt!(str)
  ret=pbCsvField!(str)
  if !ret[/\A\d+$/]
    raise _INTL("Field {1} is not a positive integer",ret)
  end
  return ret.to_i
end

def pbEventCommentInput(*args)
  parameters = []
  list = *args[0].list # Event or event page
  elements = *args[1] # Number of elements
  trigger = *args[2] # Trigger
  return nil if list == nil
  return nil unless list.is_a?(Array)
  for item in list
    next unless item.code == 108 || item.code == 408
    if item.parameters[0] == trigger
      start = list.index(item) + 1
      finish = start + elements
      for id in start...finish
        next if !list[id]
        parameters.push(list[id].parameters[0])
      end
      return parameters
    end
  end
  return nil
end

def pbCurrentEventCommentInput(elements,trigger)
  return nil if !pbMapInterpreterRunning?
  event=pbMapInterpreter.get_character(0)
  return nil if !event
  return pbEventCommentInput(event,elements,trigger)
end



module InterpreterMixin
  def pbGlobalLock # Freezes all events on the map (for use at the beginning of common events)
    for event in $game_map.events.values
      event.minilock
    end
  end

  def pbGlobalUnlock # Unfreezes all events on the map (for use at the end of common events)
    for event in $game_map.events.values
      event.unlock
    end
  end

  def pbRepeatAbove(index)
    index=@list[index].indent
    loop do
      index-=1
      if @list[index].indent==indent
        return index+1
      end
    end
  end

  def pbBreakLoop(index)
    indent = @list[index].indent
    temp_index=index
    # Copy index to temporary variables
    loop do
      # Advance index
      temp_index += 1
      # If a fitting loop was not found
      if temp_index >= @list.size-1
        return index+1
      end
      if @list[temp_index].code == 413 and @list[temp_index].indent < indent
        return temp_index+1
      end
    end
  end

  def pbJumpToLabel(index,label_name)
    temp_index = 0
    loop do
      if temp_index >= @list.size-1
        return index+1
      end
      if @list[temp_index].code == 118 and
         @list[temp_index].parameters[0] == label_name
        return temp_index+1
      end
      temp_index += 1
    end
  end

# Gets the next index in the interpreter, ignoring
# certain events between messages
  def pbNextIndex(index)
    return -1 if !@list || @list.length==0
    i=index+1
    loop do
      if i>[email protected]
        return i
      end
      code=@list[i].code
      case code
      when 118, 108, 408 # Label, Comment
        i+=1
      when 413 # Repeat Above
        i=pbRepeatAbove(i)
      when 113 # Break Loop
        i=pbBreakLoop(i)
      when 119 # Jump to Label
        newI=pbJumpToLabel(i,@list[i].parameters[0])
        if newI>i
          i=newI
        else
          i+=1
        end
      else
        return i
      end     
    end
  end

# Helper function that shows a picture in a script.  To be used in
# a script event command.
  def pbShowPicture(number,name,origin,x,y,zoomX=100,zoomY=100,opacity=255,blendType=0)
    number = number + ($game_temp.in_battle ? 50 : 0)
    $game_screen.pictures[number].show(name,origin,
       x, y, zoomX,zoomY,opacity,blendType)
  end

# Erases an event and adds it to the list of erased events so that
# it can stay erased when the game is saved then loaded again.  To be used in
# a script event command.
  def pbEraseThisEvent
    if $game_map.events[@event_id]
      $game_map.events[@event_id].erase
      $PokemonMap.addErasedEvent(@event_id) if $PokemonMap
    end
    @index+=1
    return true
  end

# Runs a common event.  To be used in a script event command.
  def pbCommonEvent(id)
    if $game_temp.in_battle
      $game_temp.common_event_id = id
    else
      commonEvent = $data_common_events[id]
      $game_system.battle_interpreter.setup(commonEvent.list, 0)
    end
  end

# Sets another event's self switch (eg. pbSetSelfSwitch(20,"A",true) ).
# To be used in a script event command.
  def pbSetSelfSwitch(event,swtch,value)
    $game_self_switches[[@map_id,event,swtch]]=value
    $game_map.need_refresh = true
  end

# Must use this approach to share the methods because the methods already
# defined in a class override those defined in an included module
  CustomEventCommands=<<_END_

  def command_242
    pbBGMFade(pbParams[0])
    return true
  end

  def command_246
    pbBGSFade(pbParams[0])
    return true
  end

  def command_251
    pbSEStop()
    return true
  end

  def command_241
    pbBGMPlay(pbParams[0])
    return true
  end

  def command_245
    pbBGSPlay(pbParams[0])
    return true
  end

  def command_249
    pbMEPlay(pbParams[0])
    return true
  end

  def command_250
    pbSEPlay(pbParams[0])
    return true
  end
_END_
end



def pbButtonInputProcessing(variableNumber=0,timeoutFrames=0)
  ret=0
  loop do
    Graphics.update
    Input.update
    pbUpdateSceneMap
    for i in 1..18
      if Input.trigger?(i)
        ret=i
      end
    end
    break if ret!=0
    if timeoutFrames && timeoutFrames>0
      i+=1
      break if i>=timeoutFrames
    end
  end
  Input.update
  if variableNumber && variableNumber>0
    $game_variables[variableNumber]=ret
    $game_map.need_refresh = true if $game_map
  end
  return ret
end



class Game_Temp
  attr_accessor :background
end



class Game_Interpreter   # Used by RMVX
  include InterpreterMixin
  eval(InterpreterMixin::CustomEventCommands)
  @@immediateDisplayAfterWait=false
  @buttonInput=false

  def pbParams
    return @params
  end

  def command_105
    return false if @buttonInput
    @buttonInput=true
    pbButtonInputProcessing(@list[@index].parameters[0])
    @buttonInput=false
    @index+=1
    return true
  end

  def command_101
    if $game_temp.message_window_showing
      return false
    end
    $game_message=Game_Message.new if !$game_message
    message=""
    commands=nil
    numInputVar=nil
    numInputDigitsMax=nil
    text=""
    facename=@list[@index].parameters[0]
    faceindex=@list[@index].parameters[1]
    if facename && facename!=""
      text+="\\ff[#{facename},#{faceindex}]"
    end
    if $game_message
      $game_message.background=@list[@index].parameters[2]
    end
    $game_system.message_position=@list[@index].parameters[3]
    message+=text
    messageend=""
    loop do
      nextIndex=pbNextIndex(@index)
      code=@list[nextIndex].code
      if code == 401
        text=@list[nextIndex].parameters[0]
        text+=" " if text!="" && text[text.length-1,1]!=" "
        message+=text
        @index=nextIndex
      else
        if code == 102
          commands=@list[nextIndex].parameters
          @index=nextIndex
        elsif code == 106 && @@immediateDisplayAfterWait
          params=@list[nextIndex].parameters
          if params[0]<=10
            nextcode=@list[nextIndex+1].code
            if nextcode==101||nextcode==102||nextcode==103
              @index=nextIndex
            else
              break
            end
          else
            break
          end
        elsif code == 103
          numInputVar=@list[nextIndex].parameters[0]
          numInputDigitsMax=@list[nextIndex].parameters[1]
          @index=nextIndex
        elsif code == 101
          messageend="\1"
        end
        break
      end
    end
    message=_MAPINTL($game_map.map_id,message)
    @message_waiting=true
    if commands
      cmdlist=[]
      for cmd in commands[0]
        cmdlist.push(_MAPINTL($game_map.map_id,cmd))
      end
      command=Kernel.pbMessage(message+messageend,cmdlist,commands[1])
      @branch[@list[@index].indent] = command
    elsif numInputVar
      params=ChooseNumberParams.new
      params.setMaxDigits(numInputDigitsMax)
      params.setDefaultValue($game_variables[numInputVar])
      $game_variables[numInputVar]=Kernel.pbMessageChooseNumber(message+messageend,params)
      $game_map.need_refresh = true if $game_map
    else
      Kernel.pbMessage(message+messageend)
    end
    @message_waiting=false
    return true
  end

  def command_102
    @message_waiting=true
    command=Kernel.pbShowCommands(nil,@list[@index].parameters[0],@list[@index].parameters[1])
    @message_waiting=false
    @branch[@list[@index].indent] = command
    Input.update # Must call Input.update again to avoid extra triggers
    return true
  end

  def command_103
    varnumber=@list[@index].parameters[0]
    @message_waiting=true
    params=ChooseNumberParams.new
    params.setMaxDigits(@list[@index].parameters[1])
    params.setDefaultValue($game_variables[varnumber])
    $game_variables[varnumber]=Kernel.pbChooseNumber(nil,params)
    $game_map.need_refresh = true if $game_map
    @message_waiting=false
    return true
  end
end



class Interpreter   # Used by RMXP
  include InterpreterMixin
  eval(InterpreterMixin::CustomEventCommands)
  @@immediateDisplayAfterWait=false
  @buttonInput=false

  def pbParams
    return @parameters
  end

  def command_105
    return false if @buttonInput
    @buttonInput=true
    pbButtonInputProcessing(@list[@index].parameters[0])
    @buttonInput=false
    @index+=1
    return true
  end

  def command_101
    if $game_temp.message_window_showing
      return false
    end
    message=""
    commands=nil
    numInputVar=nil
    numInputDigitsMax=nil
    text=""
    firstText=nil
    if @list[@index].parameters.length==1
      text+=@list[@index].parameters[0]
      firstText=@list[@index].parameters[0]
      text+=" " if text[text.length-1,1]!=" "
      message+=text
    else
      facename=@list[@index].parameters[0]
      faceindex=@list[@index].parameters[1]
      if facename && facename!=""
        text+="\\ff[#{facename},#{faceindex}]"
        message+=text
      end
    end
    messageend=""
    loop do
      nextIndex=pbNextIndex(@index)
      code=@list[nextIndex].code
      if code == 401
        text=@list[nextIndex].parameters[0]
        text+=" " if text[text.length-1,1]!=" "
        message+=text
        @index=nextIndex
      else
        if code == 102
          commands=@list[nextIndex].parameters
          @index=nextIndex
        elsif code == 106 && @@immediateDisplayAfterWait
          params=@list[nextIndex].parameters
          if params[0]<=10
            nextcode=@list[nextIndex+1].code
            if nextcode==101||nextcode==102||nextcode==103
              @index=nextIndex
            else
              break
            end
          else
            break
          end
        elsif code == 103
          numInputVar=@list[nextIndex].parameters[0]
          numInputDigitsMax=@list[nextIndex].parameters[1]
          @index=nextIndex
        elsif code == 101
          if @list[@index].parameters.length==1
            text=@list[@index].parameters[0]
            if text[/\A\\ignr/] && text==firstText
              text+=" " if text[text.length-1,1]!=" "
              message+=text
              @index=nextIndex
              continue
            end
          end
          messageend="\1"
        end
        break
      end
    end
    @message_waiting=true # needed to allow parallel process events to work while
                          # a message is displayed
    message=_MAPINTL($game_map.map_id,message)
    if commands
      cmdlist=[]
      for cmd in commands[0]
        cmdlist.push(_MAPINTL($game_map.map_id,cmd))
      end
      command=Kernel.pbMessage(message+messageend,cmdlist,commands[1])
      @branch[@list[@index].indent] = command
    elsif numInputVar
      params=ChooseNumberParams.new
      params.setMaxDigits(numInputDigitsMax)
      params.setDefaultValue($game_variables[numInputVar])
      $game_variables[numInputVar]=Kernel.pbMessageChooseNumber(message+messageend,params)
      $game_map.need_refresh = true if $game_map
    else
      Kernel.pbMessage(message+messageend,nil)
    end
    @message_waiting=false
    return true
  end

  def command_102
    @message_waiting=true
    command=Kernel.pbShowCommands(nil,@list[@index].parameters[0],@list[@index].parameters[1])
    @message_waiting=false
    @branch[@list[@index].indent] = command
    Input.update # Must call Input.update again to avoid extra triggers
    return true
  end

  def command_103
    varnumber=@list[@index].parameters[0]
    @message_waiting=true
    params=ChooseNumberParams.new
    params.setMaxDigits(@list[@index].parameters[1])
    params.setDefaultValue($game_variables[varnumber])
    $game_variables[varnumber]=Kernel.pbChooseNumber(nil,params)
    $game_map.need_refresh = true if $game_map
    @message_waiting=false
    return true
  end
end



class ChooseNumberParams
  def initialize
    @maxDigits=0
    @minNumber=0
    @maxNumber=0
    @skin=nil
    @messageSkin=nil
    @negativesAllowed=false
    @initialNumber=0
    @cancelNumber=nil
  end

  def setMessageSkin(value)
    @messageSkin=value
  end

  def messageSkin # Set the full path for the message's window skin
    @messageSkin
  end

  def setSkin(value)
    @skin=value
  end

  def skin
    @skin
  end

  def setNegativesAllowed(value)
    @negativeAllowed=value
  end

  def negativesAllowed
    @negativeAllowed ? true : false
  end

  def setRange(minNumber,maxNumber)
    maxNumber=minNumber if minNumber>maxNumber
    @maxDigits=0
    @minNumber=minNumber
    @maxNumber=maxNumber
  end

  def setDefaultValue(number)
    @initialNumber=number
    @cancelNumber=nil
  end

  def setInitialValue(number)
    @initialNumber=number
  end

  def setCancelValue(number)
    @cancelNumber=number
  end

  def initialNumber
    return clamp(@initialNumber,self.minNumber,self.maxNumber)
  end

  def cancelNumber
    return @cancelNumber ? @cancelNumber : self.initialNumber
  end

  def minNumber
    ret=0
    if @maxDigits>0
      ret=-((10**@maxDigits)-1)
    elsif
      ret=@minNumber
    end
    ret=0 if !@negativeAllowed && ret<0
    return ret
  end

  def maxNumber
    ret=0
    if @maxDigits>0
      ret=((10**@maxDigits)-1)
    elsif
      ret=@maxNumber
    end
    ret=0 if !@negativeAllowed && ret<0
    return ret
  end

  def setMaxDigits(value)
    @maxDigits=[1,value].max
  end

  def maxDigits
    if @maxDigits>0
      return @maxDigits
    else
      return [numDigits(self.minNumber),numDigits(self.maxNumber)].max
    end
  end

  private

  def clamp(v,mn,mx)
    return v<mn ? mn : (v>mx ? mx : v)
  end

  def numDigits(number)
    ans = 1
    number=number.abs
    while number >= 10
      ans+=1
      number/=10
    end
    return ans
  end
end



def pbChooseNumber(msgwindow,params)
  return 0 if !params
  ret=0
  maximum=params.maxNumber
  minimum=params.minNumber
  defaultNumber=params.initialNumber
  cancelNumber=params.cancelNumber
  cmdwindow=Window_InputNumberPokemon.new(params.maxDigits)
  cmdwindow.z=99999
  cmdwindow.visible=true
  cmdwindow.setSkin(params.skin) if params.skin
  cmdwindow.sign=params.negativesAllowed # must be set before number
  cmdwindow.number=defaultNumber
  curnumber=defaultNumber
  pbPositionNearMsgWindow(cmdwindow,msgwindow,:right)
  command=0
  loop do
    Graphics.update
    Input.update
    pbUpdateSceneMap
    cmdwindow.update
    msgwindow.update if msgwindow
    yield if block_given?
    if Input.trigger?(Input::C)
      ret=cmdwindow.number
      if ret>maximum
        pbPlayBuzzerSE()
      elsif ret<minimum
        pbPlayBuzzerSE()
      else
        pbPlayDecisionSE()
        break
      end
    elsif Input.trigger?(Input::B)
      pbPlayCancelSE()
      ret=cancelNumber
      break
    end
  end
  cmdwindow.dispose
  Input.update
  return ret 
end

def Kernel.pbShowCommandsWithHelp(msgwindow,commands,help,cmdIfCancel=0,defaultCmd=0)
  msgwin=msgwindow
  if !msgwindow
    msgwin=Kernel.pbCreateMessageWindow(nil)
  end
  oldlbl=msgwin.letterbyletter
  msgwin.letterbyletter=false
  if commands
    cmdwindow=Window_CommandPokemonEx.new(commands)
    cmdwindow.z=99999
    cmdwindow.visible=true
    cmdwindow.resizeToFit(cmdwindow.commands)
    cmdwindow.height=msgwin.y if cmdwindow.height>msgwin.y
    cmdwindow.index=defaultCmd
    command=0
    msgwin.text=help[cmdwindow.index]
    msgwin.width=msgwin.width # Necessary evil to make it use the proper margins.
    loop do
      Graphics.update
      Input.update
      oldindex=cmdwindow.index
      cmdwindow.update
      if oldindex!=cmdwindow.index
        msgwin.text=help[cmdwindow.index]
      end
      msgwin.update
      yield if block_given?
      if Input.trigger?(Input::B)
        if cmdIfCancel>0
          command=cmdIfCancel-1
          break
        elsif cmdIfCancel<0
          command=cmdIfCancel
          break
        end
      end
      if Input.trigger?(Input::C)
        command=cmdwindow.index
        break
      end
      pbUpdateSceneMap
    end
    ret=command
    cmdwindow.dispose
    Input.update
  end
  msgwin.letterbyletter=oldlbl
  if !msgwindow
    msgwin.dispose
  end
  return ret
end

def Kernel.pbShowCommands(msgwindow,commands=nil,cmdIfCancel=0,defaultCmd=0)
  ret=0
  if commands
    cmdwindow=Window_CommandPokemonEx.new(commands)
    cmdwindow.z=99999
    cmdwindow.visible=true
    cmdwindow.resizeToFit(cmdwindow.commands)
    pbPositionNearMsgWindow(cmdwindow,msgwindow,:right)
    cmdwindow.index=defaultCmd
    command=0
    loop do
      Graphics.update
      Input.update
      cmdwindow.update
      msgwindow.update if msgwindow
      yield if block_given?
      if Input.trigger?(Input::B)
        if cmdIfCancel>0
          command=cmdIfCancel-1
          break
        elsif cmdIfCancel<0
          command=cmdIfCancel
          break
        end
      end
      if Input.trigger?(Input::C)
        command=cmdwindow.index
        break
      end
      pbUpdateSceneMap
    end
    ret=command
    cmdwindow.dispose
    Input.update
  end
  return ret
end

def pbPositionFaceWindow(facewindow,msgwindow)
  return if !facewindow
  if msgwindow
    if facewindow.height<=msgwindow.height
      facewindow.y=msgwindow.y
    else
      facewindow.y=msgwindow.y+msgwindow.height-facewindow.height
    end
    facewindow.x=Graphics.width-facewindow.width
    msgwindow.x=0
    msgwindow.width=Graphics.width-facewindow.width
  else
    facewindow.height=Graphics.height if facewindow.height>Graphics.height
    facewindow.x=0
    facewindow.y=0
  end
end

def pbPositionNearMsgWindow(cmdwindow,msgwindow,side)
  return if !cmdwindow
  if msgwindow
    height=[cmdwindow.height,Graphics.height-msgwindow.height].min
    if cmdwindow.height!=height
      cmdwindow.height=height
    end
    cmdwindow.y=msgwindow.y-cmdwindow.height
    if cmdwindow.y<0
      cmdwindow.y=msgwindow.y+msgwindow.height
      if cmdwindow.y+cmdwindow.height>Graphics.height
        cmdwindow.y=msgwindow.y-cmdwindow.height
      end
    end
    case side
    when :left
      cmdwindow.x=msgwindow.x
    when :right
      cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
    else
      cmdwindow.x=msgwindow.x+msgwindow.width-cmdwindow.width
    end
  else
    cmdwindow.height=Graphics.height if cmdwindow.height>Graphics.height
    cmdwindow.x=0
    cmdwindow.y=0
  end
end

def pbGetBasicMapNameFromId(id)
  begin
    map = pbLoadRxData("Data/MapInfos")
    return "" if !map
    return map[id].name
  rescue
    return ""
  end
end

def pbGetMapNameFromId(id)
  map=pbGetBasicMapNameFromId(id)
  if $Trainer
    map.gsub!(/\\PN/,$Trainer.name)
  end
  return map
end

#~~ Pokémon Contests ~~ Required
def Kernel.pbCustomMessage(message,skin=nil,newx=nil,newwidth=nil,&block)
  ret=0
  msgwindow=Kernel.pbCreateMessageWindow(nil,skin)
  msgwindow.x=newx if newx!=nil
  if newwidth!=nil
    msgwindow.width=newwidth
  else
  msgwindow.width=Graphics.width-msgwindow.x
end
  Kernel.pbMessageDisplay(msgwindow,message,&block)
  Kernel.pbDisposeMessageWindow(msgwindow)
  Input.update
  return ret
end
#~~

def Kernel.pbMessage(message,commands=nil,cmdIfCancel=0,skin=nil,defaultCmd=0,&block)
  ret=0
  msgwindow=Kernel.pbCreateMessageWindow(nil,skin)
  if commands
    ret=Kernel.pbMessageDisplay(msgwindow,message,true,
       proc {|msgwindow|
          next Kernel.pbShowCommands(msgwindow,commands,cmdIfCancel,defaultCmd,&block)
    },&block)
  else
    Kernel.pbMessageDisplay(msgwindow,message,&block)
  end
  Kernel.pbDisposeMessageWindow(msgwindow)
  Input.update
  return ret
end

def Kernel.pbMessageChooseNumber(message,params,&block)
  msgwindow=Kernel.pbCreateMessageWindow(nil,params.messageSkin)
  ret=Kernel.pbMessageDisplay(msgwindow,message,true,
     proc {|msgwindow|
        next Kernel.pbChooseNumber(msgwindow,params,&block)
  },&block)
  Kernel.pbDisposeMessageWindow(msgwindow)
  return ret
end

def Kernel.pbConfirmMessage(message,&block)
  return (Kernel.pbMessage(message,[_INTL("Yes"),_INTL("No")],2,&block)==0)
end

def Kernel.pbConfirmMessageSerious(message,&block)
  return (Kernel.pbMessage(message,[_INTL("No"),_INTL("Yes")],1,&block)==1)
end

def Kernel.pbCreateStatusWindow(viewport=nil)
  msgwindow=Window_AdvancedTextPokemon.new("")
  if !viewport
    msgwindow.z=99999
  else
    msgwindow.viewport=viewport
  end
  msgwindow.visible=false
  msgwindow.letterbyletter=false
  pbBottomLeftLines(msgwindow,2)
  skinfile=MessageConfig.pbGetSpeechFrame()
  msgwindow.setSkin(skinfile)
  return msgwindow
end

def Kernel.pbCreateMessageWindow(viewport=nil,skin=nil)
  msgwindow=Window_AdvancedTextPokemon.new("")
  if !viewport
    msgwindow.z=99999
  else
    msgwindow.viewport=viewport
  end
  msgwindow.visible=true
  msgwindow.letterbyletter=true
  msgwindow.back_opacity=MessageConfig::WindowOpacity
  pbBottomLeftLines(msgwindow,2)
  $game_temp.message_window_showing=true if $game_temp
  $game_message.visible=true if $game_message
  skin=MessageConfig.pbGetSpeechFrame() if !skin
  msgwindow.setSkin(skin)
  return msgwindow
end

def Kernel.pbDisposeMessageWindow(msgwindow)
  $game_temp.message_window_showing=false if $game_temp
  $game_message.visible=false if $game_message
  msgwindow.dispose
end



class FaceWindowVX < SpriteWindow_Base 
  def initialize(face)
    super(0,0,128,128)
    faceinfo=face.split(",")
    facefile=pbResolveBitmap("Graphics/Faces/"+faceinfo[0])
    facefile=pbResolveBitmap("Graphics/Pictures/"+faceinfo[0]) if !facefile
    self.contents.dispose if self.contents
    @faceIndex=faceinfo[1].to_i
    @facebitmaptmp=AnimatedBitmap.new(facefile)
    @facebitmap=BitmapWrapper.new(96,96)
    @facebitmap.blt(0,0,@facebitmaptmp.bitmap,Rect.new(
       (@faceIndex % 4) * 96,
       (@faceIndex / 4) * 96, 96, 96
    ))
    self.contents=@facebitmap
  end

  def update
    super
    if @facebitmaptmp.totalFrames>1
      @facebitmaptmp.update
      @facebitmap.blt(0,0,@facebitmaptmp.bitmap,Rect.new(
         (@faceIndex % 4) * 96,
         (@faceIndex / 4) * 96, 96, 96
      ))
    end
  end

  def dispose
    @facebitmaptmp.dispose
    @facebitmap.dispose if @facebitmap
    super
  end
end



def itemIconTag(item)
  return "" if !item
  if item.respond_to?("icon_name")
    return sprintf("<icon=%s>",item.icon_name)
  else
    ix=item.icon_index % 16 * 24
    iy=item.icon_index / 16 * 24
    return sprintf("<img=Graphics/System/Iconset|%d|%d|24|24>",ix,iy)
  end
end

def getSkinColor(windowskin,color,isDarkSkin)
  if !windowskin || windowskin.disposed? || 
     windowskin.width!=128 || windowskin.height!=128
    textcolors=[
       isDarkSkin ? shadowc3tag(MessageConfig::LIGHTTEXTBASE, MessageConfig::LIGHTTEXTSHADOW) :
                    shadowc3tag(MessageConfig::DARKTEXTBASE, MessageConfig::DARKTEXTSHADOW),
       "<c2=7E105D08>",   # Red
       "<c2=421F2117>",   # Blue
       "<c2=43F022E8>",   # Green
       "<c2=7FF05EE8>",   # Yellow
       "<c2=7E1F5D17>",   # Magenta
       "<c2=43FF22F7>",   # Cyan
       "<c2=63184210>",   # Grey
       "<c2=7FFF5EF7>"    # White
    ]
    color=0 if color>textcolors.length
    return textcolors[color]
  else # VX windowskin
    color=0 if color>=32
    x = 64 + (color % 8) * 8
    y = 96 + (color / 8) * 8
    pixel=windowskin.get_pixel(x, y)
    return shadowctagFromColor(pixel)
  end
end

# internal function
def pbRepositionMessageWindow(msgwindow, linecount=2)
  msgwindow.height=32*linecount+msgwindow.borderY
  msgwindow.y=(Graphics.height)-(msgwindow.height)
  if $game_temp && $game_temp.in_battle && !$scene.respond_to?("update_basic")
    msgwindow.y=0
  elsif $game_system && $game_system.respond_to?("message_position")
    case $game_system.message_position
    when 0  # up
      msgwindow.y=0
    when 1  # middle
      msgwindow.y=(Graphics.height/2)-(msgwindow.height/2)
    when 2
     msgwindow.y=(Graphics.height)-(msgwindow.height)
    end
  end
  if $game_system && $game_system.respond_to?("message_frame")
    if $game_system.message_frame != 0
      msgwindow.opacity = 0
    end
  end
  if $game_message
    case $game_message.background
    when 1  # dim
      msgwindow.opacity=0
    when 2  # transparent
      msgwindow.opacity=0
    end 
  end
end

# internal function
def pbUpdateMsgWindowPos(msgwindow,event,eventChanged=false)
  if event
    if eventChanged
      msgwindow.resizeToFit2(msgwindow.text,Graphics.width*2/3,msgwindow.height)
    end
    msgwindow.y=event.screen_y-48-msgwindow.height  
    if msgwindow.y<0
      msgwindow.y=event.screen_y+24
    end
    msgwindow.x=event.screen_x-(msgwindow.width/2)
    msgwindow.x=0 if msgwindow.x<0
    if msgwindow.x>Graphics.width-msgwindow.width
      msgwindow.x=Graphics.width-msgwindow.width
    end
  else
    curwidth=msgwindow.width
    if curwidth!=Graphics.width
      msgwindow.width=Graphics.width
      msgwindow.width=Graphics.width     
    end
  end
end

# internal function

def pbGetGoldString
  moneyString=""
  if $Trainer
    moneyString=_INTL("${1}",$Trainer.money)
  else
    if $data_system.respond_to?("words")
      moneyString=_INTL("{1} {2}",$game_party.gold,$data_system.words.gold)
    else
      moneyString=_INTL("{1} {2}",$game_party.gold,Vocab.gold)         
    end
  end
  return moneyString
end

def pbDisplayGoldWindow(msgwindow)
  moneyString=pbGetGoldString()
  goldwindow=Window_AdvancedTextPokemon.new(_INTL("Money:\n<ar>{1}</ar>",moneyString))
  goldwindow.setSkin("Graphics/Windowskins/goldskin")
  goldwindow.resizeToFit(goldwindow.text,Graphics.width)
  goldwindow.width=160 if goldwindow.width<=160
  if msgwindow.y==0
    goldwindow.y=Graphics.height-goldwindow.height
  else
    goldwindow.y=0
  end
  goldwindow.viewport=msgwindow.viewport
  goldwindow.z=msgwindow.z
  return goldwindow
end

def pbDisplayCoinsWindow(msgwindow,goldwindow)
  coinString=($PokemonGlobal) ? $PokemonGlobal.coins : "0"
  coinwindow=Window_AdvancedTextPokemon.new(_INTL("Coins:\n<ar>{1}</ar>",coinString))
  coinwindow.setSkin("Graphics/Windowskins/goldskin")
  coinwindow.resizeToFit(coinwindow.text,Graphics.width)
  coinwindow.width=160 if coinwindow.width<=160
  if msgwindow.y==0
    coinwindow.y=(goldwindow) ? goldwindow.y-coinwindow.height : Graphics.height-coinwindow.height
  else
    coinwindow.y=(goldwindow) ? goldwindow.height : 0
  end
  coinwindow.viewport=msgwindow.viewport
  coinwindow.z=msgwindow.z
  return coinwindow
end

def pbMessageWaitForInput(msgwindow,frames,showPause=false)
  return if !frames || frames<=0
  if msgwindow && showPause
    msgwindow.startPause
  end
  frames.times do
    Graphics.update
    Input.update
    msgwindow.update if msgwindow
    pbUpdateSceneMap
    if Input.trigger?(Input::C) || Input.trigger?(Input::B)
      break
    end
    yield if block_given?
  end
  if msgwindow && showPause
    msgwindow.stopPause
  end
end

def Kernel.pbMessageDisplay(msgwindow,message,letterbyletter=true,commandProc=nil)
  return if !msgwindow
  oldletterbyletter=msgwindow.letterbyletter
  msgwindow.letterbyletter=(letterbyletter ? true : false)
  ret=nil
  count=0
  commands=nil
  facewindow=nil
  goldwindow=nil
  coinwindow=nil
  cmdvariable=0
  cmdIfCancel=0
  msgwindow.waitcount=0
  autoresume=false
  text=message.clone
  msgback=nil
  linecount=(Graphics.height>400) ? 3 : 2
  ### Text replacement
  text.gsub!(/\\\\/,"\5")
  if $game_actors
    text.gsub!(/\\[Nn]\[([1-8])\]/){ 
       m=$1.to_i
       next $game_actors[m].name
    }
  end
  text.gsub!(/\\[Ss][Ii][Gg][Nn]\[([^\]]*)\]/){ 
     next "\\op\\cl\\ts[]\\w["+$1+"]"
  }
  text.gsub!(/\\[Pp][Nn]/,$Trainer.name) if $Trainer
  text.gsub!(/\\[Pp][Mm]/,_INTL("${1}",$Trainer.money)) if $Trainer
  text.gsub!(/\\[Nn]/,"\n")
  text.gsub!(/\\\[([0-9A-Fa-f]{8,8})\]/){ "<c2="+$1+">" }
  text.gsub!(/\\[Pp][Gg]/,"\\b") if $Trainer && $Trainer.isMale?
  text.gsub!(/\\[Pp][Gg]/,"\\r") if $Trainer && $Trainer.isFemale?
  text.gsub!(/\\[Pp][Oo][Gg]/,"\\r") if $Trainer && $Trainer.isMale?
  text.gsub!(/\\[Pp][Oo][Gg]/,"\\b") if $Trainer && $Trainer.isFemale?
  text.gsub!(/\\[Pp][Gg]/,"")
  text.gsub!(/\\[Pp][Oo][Gg]/,"")
  text.gsub!(/\\[Bb]/,"<c2=6546675A>")
  text.gsub!(/\\[Rr]/,"<c2=043C675A>")
  text.gsub!(/\\1/,"\1")
  colortag=""
  isDarkSkin=isDarkWindowskin(msgwindow.windowskin)
  if ($game_message && $game_message.background>0) ||
     ($game_system && $game_system.respond_to?("message_frame") &&
      $game_system.message_frame != 0)
    colortag=getSkinColor(msgwindow.windowskin,0,true)
  else
    colortag=getSkinColor(msgwindow.windowskin,0,isDarkSkin)
  end
  text.gsub!(/\\[Cc]\[([0-9]+)\]/){ 
     m=$1.to_i
     next getSkinColor(msgwindow.windowskin,m,isDarkSkin)
  }
  begin
    last_text = text.clone
    text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
  end until text == last_text
  begin
    last_text = text.clone
    text.gsub!(/\\[Ll]\[([0-9]+)\]/) { 
       linecount=[1,$1.to_i].max;
       next "" 
    }
  end until text == last_text
  text=colortag+text
  ### Controls
  textchunks=[]
  controls=[]
  while text[/(?:\\([WwFf]|[Ff][Ff]|[Tt][Ss]|[Cc][Ll]|[Mm][Ee]|[Ss][Ee]|[Ww][Tt]|[Ww][Tt][Nn][Pp]|[Cc][Hh])\[([^\]]*)\]|\\([Gg]|[Cc][Nn]|[Ww][Dd]|[Ww][Mm]|[Oo][Pp]|[Cc][Ll]|[Ww][Uu]|[\.]|[\|]|[\!]|[\x5E])())/i]
    textchunks.push($~.pre_match)
    if $~[1]
      controls.push([$~[1].downcase,$~[2],-1])
    else
      controls.push([$~[3].downcase,"",-1])
    end
    text=$~.post_match
  end
  textchunks.push(text)
  for chunk in textchunks
    chunk.gsub!(/\005/,"\\")
  end
  textlen=0
  for i in 0...controls.length
    control=controls[i][0]
    if control=="wt" || control=="wtnp" || control=="." || control=="|"
      textchunks[i]+="\2"
    elsif control=="!"
      textchunks[i]+="\1"
    end
    textlen+=toUnformattedText(textchunks[i]).scan(/./m).length
    controls[i][2]=textlen
  end
  text=textchunks.join("")
  unformattedText=toUnformattedText(text)
  signWaitCount=0
  haveSpecialClose=false
  specialCloseSE=""
  for i in 0...controls.length
    control=controls[i][0]
    param=controls[i][1]
    if control=="f"
      facewindow.dispose if facewindow
      facewindow=PictureWindow.new("Graphics/Pictures/#{param}")
    elsif control=="op"
      signWaitCount=21
    elsif control=="cl"
      text=text.sub(/\001\z/,"") # fix: '$' can match end of line as well
      haveSpecialClose=true
      specialCloseSE=param
    elsif control=="se" && controls[i][2]==0
      startSE=param
      controls[i]=nil
    elsif control=="ff"
      facewindow.dispose if facewindow
      facewindow=FaceWindowVX.new(param)
    elsif control=="ch"
      cmds=param.clone
      cmdvariable=pbCsvPosInt!(cmds)
      cmdIfCancel=pbCsvField!(cmds).to_i
      commands=[]
      while cmds.length>0
        commands.push(pbCsvField!(cmds))
      end
    elsif control=="wtnp" || control=="^"
      text=text.sub(/\001\z/,"") # fix: '$' can match end of line as well
    end
  end
  if startSE!=nil
    pbSEPlay(pbStringToAudioFile(startSE))
  elsif signWaitCount==0 && letterbyletter
    pbPlayDecisionSE()
  end
  ########## Position message window  ##############
  pbRepositionMessageWindow(msgwindow,linecount)
  if $game_message && $game_message.background==1
    msgback=IconSprite.new(0,msgwindow.y,msgwindow.viewport)
    msgback.z=msgwindow.z-1
    msgback.setBitmap("Graphics/System/MessageBack")
  end
  if facewindow
    pbPositionNearMsgWindow(facewindow,msgwindow,:left)
    facewindow.viewport=msgwindow.viewport
    facewindow.z=msgwindow.z
  end
  atTop=(msgwindow.y==0)
  ########## Show text #############################
  msgwindow.text=text
  Graphics.frame_reset if Graphics.frame_rate>40
  begin
    if signWaitCount>0
      signWaitCount-=1
      if atTop
        msgwindow.y=-(msgwindow.height*(signWaitCount)/20)
      else
        msgwindow.y=Graphics.height-(msgwindow.height*(20-signWaitCount)/20)
      end
    end
    for i in 0...controls.length
      if controls[i] && controls[i][2]<=msgwindow.position && msgwindow.waitcount==0
        control=controls[i][0]
        param=controls[i][1]
        case control
        when "f"
          facewindow.dispose if facewindow
          facewindow=PictureWindow.new("Graphics/Pictures/#{param}")
          pbPositionNearMsgWindow(facewindow,msgwindow,:left)
          facewindow.viewport=msgwindow.viewport
          facewindow.z=msgwindow.z
        when "ts"
          if param==""
            msgwindow.textspeed=-999
          else
            msgwindow.textspeed=param.to_i
          end
        when "ff"
          facewindow.dispose if facewindow
          facewindow=FaceWindowVX.new(param)
          pbPositionNearMsgWindow(facewindow,msgwindow,:left)
          facewindow.viewport=msgwindow.viewport
          facewindow.z=msgwindow.z
        when "g" # Display gold window
          goldwindow.dispose if goldwindow
          goldwindow=pbDisplayGoldWindow(msgwindow)
        when "cn" # Display coins window
          coinwindow.dispose if coinwindow
          coinwindow=pbDisplayCoinsWindow(msgwindow,goldwindow)
        when "wu"
          msgwindow.y=0
          atTop=true
          msgback.y=msgwindow.y if msgback
          pbPositionNearMsgWindow(facewindow,msgwindow,:left)
          msgwindow.y=-(msgwindow.height*(signWaitCount)/20)
        when "wm"
          atTop=false
          msgwindow.y=(Graphics.height/2)-(msgwindow.height/2)
          msgback.y=msgwindow.y if msgback
          pbPositionNearMsgWindow(facewindow,msgwindow,:left)
        when "wd"
          atTop=false
          msgwindow.y=(Graphics.height)-(msgwindow.height)
          msgback.y=msgwindow.y if msgback
          pbPositionNearMsgWindow(facewindow,msgwindow,:left)
          msgwindow.y=Graphics.height-(msgwindow.height*(20-signWaitCount)/20)
        when "."
          msgwindow.waitcount+=Graphics.frame_rate/4
        when "|"
          msgwindow.waitcount+=Graphics.frame_rate
        when "wt" # Wait
          param=param.sub(/\A\s+/,"").sub(/\s+\z/,"")
          msgwindow.waitcount+=param.to_i*2
        when "w" # Windowskin
          if param==""
            msgwindow.windowskin=nil
          else
            msgwindow.setSkin("Graphics/Windowskins/#{param}")
          end
          msgwindow.width=msgwindow.width  # Necessary evil
        when "^" # Wait, no pause
          autoresume=true
        when "wtnp" # Wait, no pause
          param=param.sub(/\A\s+/,"").sub(/\s+\z/,"")
          msgwindow.waitcount=param.to_i*2
          autoresume=true
        when "se" # Play SE
          pbSEPlay(pbStringToAudioFile(param))
        when "me" # Play ME
          pbMEPlay(pbStringToAudioFile(param))
        end
        controls[i]=nil
      end
    end
    break if !letterbyletter
    Graphics.update
    Input.update
    facewindow.update if facewindow
    if $DEBUG && Input.trigger?(Input::F6)
      pbRecord(unformattedText)
    end
    if autoresume && msgwindow.waitcount==0
      msgwindow.resume if msgwindow.busy?
      break if !msgwindow.busy?
    end
    if (Input.trigger?(Input::C) || Input.trigger?(Input::B))
      if msgwindow.busy?
        pbPlayDecisionSE() if msgwindow.pausing?
        msgwindow.resume
      else
        break if signWaitCount==0
      end
    end
    pbUpdateSceneMap
    msgwindow.update
    yield if block_given?
  end until (!letterbyletter || commandProc || commands) && !msgwindow.busy?
  Input.update # Must call Input.update again to avoid extra triggers
  msgwindow.letterbyletter=oldletterbyletter
  if commands
    $game_variables[cmdvariable]=Kernel.pbShowCommands(
       msgwindow,commands,cmdIfCancel)
    $game_map.need_refresh = true if $game_map
  end
  if commandProc
    ret=commandProc.call(msgwindow)
  end
  msgback.dispose if msgback
  goldwindow.dispose if goldwindow
  coinwindow.dispose if coinwindow
  facewindow.dispose if facewindow
  if haveSpecialClose
    pbSEPlay(pbStringToAudioFile(specialCloseSE))
    atTop=(msgwindow.y==0)
    for i in 0..20
      if atTop
        msgwindow.y=-(msgwindow.height*(i)/20)
      else
        msgwindow.y=Graphics.height-(msgwindow.height*(20-i)/20)
      end
      Graphics.update
      Input.update
      pbUpdateSceneMap
      msgwindow.update
    end
  end
  return ret
end

And don't forget to use Thread Tools Show Printable Version.
 

mewlover22

Pokemon Creator
455
Posts
15
Years
You did it i think we should make a version 16 script so people can use this so far i have found no issues im just testing a contest right now.

Edit right as round one began this happened.

---------------------------
Pokemon Essentials
---------------------------
Exception: RuntimeError

Message: Script error within event 21, map 22 (Contest Hall):

Exception: NameError

Message: Section177:1704:in `pbMoveButtons'uninitialized constant PokeContestScene::PBContestMoves

***Full script:

Kernel.pbMessage(_INTL("First up is Gary's Butterscortch!"))
showSpeciesIntro(PBSpecies::CHARIZARD,"","Butterscortch")
pbAddContestMove(2,1,2,3,7)
pbChangeContestName(2,"Butterscortch")
pbContest(50,PBSpecies::CHARIZARD,20,PBSpecies::SQUIRTLE,20,PBSpecies::HITMONTOP,20,1)


Interpreter:243:in `pbExecuteScript'

Contest:185:in `pbTurn'

Contest:115:in `pbStartContest'

Contest:2460:in `pbStartContest'

Contest:2470:in `pbContest'

(eval):5:in `pbExecuteScript'

Interpreter:1606:in `eval'

Interpreter:243:in `pbExecuteScript'

Interpreter:1606:in `command_355'

Interpreter:494:in `execute_command'



Interpreter:276:in `pbExecuteScript'

Interpreter:1606:in `command_355'

Interpreter:494:in `execute_command'

Interpreter:193:in `update'

Interpreter:106:in `loop'

Interpreter:198:in `update'

Scene_Map:103:in `update'

Scene_Map:101:in `loop'

Scene_Map:114:in `update'

Scene_Map:68:in `main'



This exception was logged in

C:\Users\Chris\Saved Games/Pokemon Essentials/errorlog.txt.

Press Ctrl+C to copy this message to the clipboard.
---------------------------
OK
---------------------------
 
31
Posts
8
Years
Well I know you should have PBContestMove above PBMove script and in
PBMove it should look like this:
Code:
class PokemonTemp
  attr_accessor :pokemonMoveData

  def pbOpenMoveData
    if !self.pokemonMoveData
      pbRgssOpen("Data/moves.dat","rb"){|f|
         self.pokemonMoveData=f.read
      }
    end
    if block_given?
      StringInput.open(self.pokemonMoveData) {|f| yield f }
    else
      return StringInput.open(self.pokemonMoveData)
    end
  end
end



class PBMoveData
  attr_reader :function,:basedamage,:type,:accuracy
  attr_reader :totalpp,:addlEffect,:target,:priority
  attr_reader :flags
  attr_reader :category,:contestType

  def initializeOld(moveid)
    movedata=pbRgssOpen("Data/rsattacks.dat")
    movedata.pos=moveid*9
    @function   = movedata.fgetb
    @basedamage = movedata.fgetb
    @type       = movedata.fgetb
    @accuracy   = movedata.fgetb
    @totalpp    = movedata.fgetb
    @addlEffect = movedata.fgetb
    @target     = movedata.fgetb
    @priority   = movedata.fgetsb
    @flags      = movedata.fgetb
    movedata.close
  end

  def initialize(moveid)
    movedata=nil
    if $PokemonTemp
      movedata=$PokemonTemp.pbOpenMoveData
    else
      movedata=pbRgssOpen("Data/moves.dat")
    end
    movedata.pos=moveid*14
    @function    = movedata.fgetw
    @basedamage  = movedata.fgetb
    @type        = movedata.fgetb
    @category    = movedata.fgetb
    @accuracy    = movedata.fgetb
    @totalpp     = movedata.fgetb
    @addlEffect  = movedata.fgetb
    @target      = movedata.fgetw
    @priority    = movedata.fgetsb
    @flags       = movedata.fgetw
    @contestType = movedata.fgetb
    movedata.close
  end
end



class PBMove
  attr_reader(:id)       # This move's ID
  attr_accessor(:pp)     # The amount of PP remaining for this move
  attr_accessor(:ppup)   # The number of PP Ups used for this move

# Gets this move's type.
  def type
    movedata=PBMoveData.new(@id)
    return movedata.type
  end

# Gets the maximum PP for this move.
  def totalpp
    movedata=PBMoveData.new(@id)
    tpp=movedata.totalpp
    return tpp+(tpp*@ppup/5).floor
  end

# Initializes this object to the specified move ID.
  def initialize(moveid)
    movedata=PBMoveData.new(moveid)
    @pp=movedata.totalpp
    @id=moveid
    @ppup=0
  end
end

And the Compiler Script should look like this:
Code:
#===============================================================================
# Exceptions and critical code
#===============================================================================
class Reset < Exception
end



def pbGetExceptionMessage(e,script="")
  emessage=e.message
  if e.is_a?(Hangup)
    emessage="The script is taking too long. The game will restart."
  elsif e.is_a?(Errno::ENOENT)
    filename=emessage.sub("No such file or directory - ", "")
    emessage="File #{filename} not found."
  end
  if emessage && !safeExists?("Game.rgssad") && !safeExists?("Game.rgss2a")
    emessage=emessage.gsub(/uninitialized constant PBItems\:\:(\S+)/){
       "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." }
    emessage=emessage.gsub(/undefined method `(\S+?)' for PBItems\:Module/){
       "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." }
    emessage=emessage.gsub(/uninitialized constant PBTypes\:\:(\S+)/){
       "The type '#{$1}' is not valid. Please add the type\r\nto the PBS/types.txt file." }
    emessage=emessage.gsub(/undefined method `(\S+?)' for PBTypes\:Module/){
       "The type '#{$1}' is not valid. Please add the type\r\nto the PBS/types.txt file." }
    emessage=emessage.gsub(/uninitialized constant PBTrainers\:\:(\S+)$/){
       "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." }
    emessage=emessage.gsub(/undefined method `(\S+?)' for PBTrainers\:Module/){
       "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." }
    emessage=emessage.gsub(/uninitialized constant PBSpecies\:\:(\S+)$/){
       "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." }
    emessage=emessage.gsub(/undefined method `(\S+?)' for PBSpecies\:Module/){
       "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." }
  end
  return emessage
end

def pbPrintException(e)
  emessage=pbGetExceptionMessage(e)
  btrace=""
  if e.backtrace
    maxlength=$INTERNAL ? 25 : 10
    e.backtrace[0,maxlength].each do |i|
      btrace=btrace+"#{i}\r\n"
    end
  end
  btrace.gsub!(/Section(\d+)/){$RGSS_SCRIPTS[$1.to_i][1]}
  message="Exception: #{e.class}\r\nMessage: #{emessage}\r\n#{btrace}"
  errorlog="errorlog.txt"
  if (Object.const_defined?(:RTP) rescue false)
    errorlog=RTP.getSaveFileName("errorlog.txt")
  end
  errorlogline=errorlog.sub(Dir.pwd+"\\","")
  errorlogline=errorlogline.sub(Dir.pwd+"/","")
  if errorlogline.length>20
    errorlogline="\r\n"+errorlogline
  end
  File.open(errorlog,"ab"){|f| f.write(message) }
  if !e.is_a?(Hangup)
    print("#{message}\r\nThis exception was logged in #{errorlogline}.\r\nPress Ctrl+C to copy this message to the clipboard.")
  end
end

def pbCriticalCode
  ret=0
  begin
    yield
    ret=1
  rescue Exception
    e=$!
    if e.is_a?(Reset) || e.is_a?(SystemExit)
      raise
    else
      pbPrintException(e)
      if e.is_a?(Hangup)
        ret=2
        raise Reset.new
      end
    end
  end
  return ret
end



#===============================================================================
# File reading
#===============================================================================
module FileLineData
  @file=""
  @linedata=""
  @lineno=0
  @section=nil
  @key=nil
  @value=nil

  def self.file
    @file
  end

  def self.file=(value)
    @file=value
  end

  def self.clear
    @file=""
    @linedata=""
    @lineno=""
    @section=nil
    @key=nil
    @value=nil
  end

  def self.linereport
    if @section
      return _INTL("File {1}, section {2}, key {3}\r\n{4}\r\n",@file,@section,@key,@value)
    else
      return _INTL("File {1}, line {2}\r\n{3}\r\n",@file,@lineno,@linedata)
    end
  end

  def self.setSection(section,key,value)
    @section=section
    @key=key
    if value && value.length>200
      @value=_INTL("{1}...",value[0,200])
    else
      @value=!value ? "" : value.clone
    end
  end

  def self.setLine(line,lineno)
    @section=nil
    if line && line.length>200
      @linedata=_INTL("{1}...",line[0,200])
    else
      @linedata=line
    end
    @lineno=lineno
  end
end



def findIndex(a)
  index=-1
  count=0
  a.each {|i|
     if yield i
       index=count
       break
     end
     count+=1
  }
  return index
end

def prepline(line)
  line.sub!(/\s*\#.*$/,"")
  line.sub!(/\s+$/,"")
  return line
end

def pbEachFileSectionEx(f)
  lineno=1
  havesection=false
  sectionname=nil
  lastsection={}
  f.each_line {|line|
     if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
       line=line[3,line.length-3]
     end
     if !line[/^\#/] && !line[/^\s*$/]
       if line[/^\s*\[\s*(.*)\s*\]\s*$/]
         if havesection
           yield lastsection,sectionname 
         end
         sectionname=$~[1]
         havesection=true
         lastsection={}
       else
        if sectionname==nil
          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)
        end
        if !line[/^\s*(\w+)\s*=\s*(.*)$/]
          raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
        end
        r1=$~[1]
        r2=$~[2]
        lastsection[r1]=r2.gsub(/\s+$/,"")
      end
    end
    lineno+=1
    if lineno%500==0
      Graphics.update
    end
    if lineno%50==0
      Win32API.SetWindowText(_INTL("Processing line {1}",lineno))
    end
  }
  if havesection
    yield lastsection,sectionname 
  end
end

def pbEachFileSection(f)
  pbEachFileSectionEx(f) {|section,name|
     if block_given? && name[/^\d+$/]
       yield section,name.to_i
     end
  }
end

def pbEachSection(f)
  lineno=1
  havesection=false
  sectionname=nil
  lastsection=[]
  f.each_line {|line|
     if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
       line=line[3,line.length-3]
     end
     if !line[/^\#/] && !line[/^\s*$/]
       if line[/^\s*\[\s*(.+?)\s*\]\s*$/]
         if havesection
           yield lastsection,sectionname 
         end
         sectionname=$~[1]
         lastsection=[]
         havesection=true
       else
         if sectionname==nil
           raise _INTL("Expected a section at the beginning of the file (line {1}). Sections begin with '[name of section]'",lineno)
         end
         lastsection.push(line.gsub(/^\s+/,"").gsub(/\s+$/,""))
       end
     end
     lineno+=1
     if lineno%500==0
       Graphics.update
     end
  }
  if havesection
    yield lastsection,sectionname 
  end
end

def pbEachCommentedLine(f)
  lineno=1
  f.each_line {|line|
     if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
       line=line[3,line.length-3]
     end
     if !line[/^\#/] && !line[/^\s*$/]
       yield line, lineno
     end
     lineno+=1
  }
end

def pbCompilerEachCommentedLine(filename)
  File.open(filename,"rb"){|f|
     FileLineData.file=filename
     lineno=1
     f.each_line {|line|
        if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
          line=line[3,line.length-3]
        end
        if !line[/^\#/] && !line[/^\s*$/]
          FileLineData.setLine(line,lineno)
          yield line, lineno
        end
        lineno+=1
     }
  }
end

def pbEachPreppedLine(f)
  lineno=1
  f.each_line {|line|
     if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
       line=line[3,line.length-3]
     end
     line=prepline(line)
     if !line[/^\#/] && !line[/^\s*$/]
       yield line, lineno
     end
     lineno+=1
  }
end

def pbCompilerEachPreppedLine(filename)
  File.open(filename,"rb"){|f|
     FileLineData.file=filename
     lineno=1
     f.each_line {|line|
        if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
          line=line[3,line.length-3]
        end
        line=prepline(line)
        if !line[/^\#/] && !line[/^\s*$/]
          FileLineData.setLine(line,lineno)
          yield line, lineno
        end
        lineno+=1
     }
  }
end

#===============================================================================
# Valid value checks
#===============================================================================
def pbCheckByte(x,valuename)
  if x<0 || x>255
    raise _INTL("The value \"{1}\" must be from 0 through 255 (0x00-0xFF in hex), got a value of {2}\r\n{3}",
       valuename,x,FileLineData.linereport)
  end
end

def pbCheckSignedByte(x,valuename)
  if x<-128 || x>127
    raise _INTL("The value \"{1}\" must be from -128 through 127, got a value of {2}\r\n{3}",
       valuename,x,FileLineData.linereport)
  end
end

def pbCheckWord(x,valuename)
  if x<0 || x>65535
    raise _INTL("The value \"{1}\" must be from 0 through 65535 (0x0000-0xFFFF in hex), got a value of {2}\r\n{3}",
       valuename,x,FileLineData.linereport)
  end
end

def pbCheckSignedWord(x,valuename)
  if x<-32768 || x>32767
    raise _INTL("The value \"{1}\" must be from -32768 through 32767, got a value of {2}\r\n{3}",
       valuename,x,FileLineData.linereport)
  end
end

#===============================================================================
# Csv parsing
#===============================================================================
def csvfield!(str)
  ret=""
  str.sub!(/^\s*/,"")
  if str[0,1]=="\""
    str[0,1]=""
    escaped=false
    fieldbytes=0
    str.scan(/./) do |s|
      fieldbytes+=s.length
      break if s=="\"" && !escaped
      if s=="\\" && !escaped
        escaped=true
      else
        ret+=s
        escaped=false
      end
    end
    str[0,fieldbytes]=""
    if !str[/^\s*,/] && !str[/^\s*$/] 
      raise _INTL("Invalid quoted field (in: {1})\r\n{2}",str,FileLineData.linereport)
    end
    str[0,str.length]=$~.post_match
  else
    if str[/,/]
      str[0,str.length]=$~.post_match
      ret=$~.pre_match
    else
      ret=str.clone
      str[0,str.length]=""
    end
    ret.gsub!(/\s+$/,"")
  end
  return ret
end

def csvquote(str)
  return "" if !str || str==""
  if str[/[,\"]/] #|| str[/^\s/] || str[/\s$/] || str[/^#/]
    str=str.gsub(/[\"]/,"\\\"")
    str="\"#{str}\""
  end
  return str
end

def csvBoolean!(str,line=-1)
  field=csvfield!(str)
  if field[/^1|[Tt][Rr][Uu][Ee]|[Yy][Ee][Ss]$/]
    return true
  elsif field[/^0|[Ff][Aa][Ll][Ss][Ee]|[Nn][Oo]$/]
    return false
  else
    raise _INTL("Field {1} is not a Boolean value (true, false, 1, 0)\r\n{2}",field,FileLineData.linereport)
    return false
  end
end

def csvInt!(str,line=-1)
  ret=csvfield!(str)
  if !ret[/^\-?\d+$/]
    raise _INTL("Field {1} is not an integer\r\n{2}",ret,FileLineData.linereport)
  end
  return ret.to_i
end

def csvPosInt!(str,line=-1)
  ret=csvfield!(str)
  if !ret[/^\d+$/]
    raise _INTL("Field {1} is not a positive integer\r\n{2}",ret,FileLineData.linereport)
  end
  return ret.to_i
end

def csvFloat!(str,key,section)
  ret=csvfield!(str)
  return Float(ret) rescue raise _INTL("Field {1} is not a number\r\n{2}",ret,FileLineData.linereport)
end

def csvEnumField!(value,enumer,key,section)
  ret=csvfield!(value)
  return checkEnumField(ret,enumer)
end

def csvEnumFieldOrInt!(value,enumer,key,section)
  ret=csvfield!(value)
  if ret[/\-?\d+/]
    return ret.to_i
  end
  return checkEnumField(ret,enumer)
end

def checkEnumField(ret,enumer)
  if enumer.is_a?(Module)
    begin
      if ret=="" || !enumer.const_defined?(ret)
        raise _INTL("Undefined value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
      end
    rescue NameError
      raise _INTL("Incorrect value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
    end
    return enumer.const_get(ret.to_sym)
  elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
    enumer=Object.const_get(enumer.to_sym)
    begin
      if ret=="" || !enumer.const_defined?(ret)
        raise _INTL("Undefined value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
      end
    rescue NameError
      raise _INTL("Incorrect value {1} in {2}\r\n{3}",ret,enumer.name,FileLineData.linereport)
    end
    return enumer.const_get(ret.to_sym)
  elsif enumer.is_a?(Array)
    idx=findIndex(enumer){|item| ret==item}
    if idx<0
      raise _INTL("Undefined value {1} (expected one of: {2})\r\n{3}",ret,enumer.inspect,FileLineData.linereport)
    end
    return idx
  elsif enumer.is_a?(Hash)
    value=enumer[ret]
    if value==nil
      raise _INTL("Undefined value {1} (expected one of: {2})\r\n{3}",ret,enumer.keys.inspect,FileLineData.linereport)
    end
    return value
  end
  raise _INTL("Enumeration not defined\r\n{1}",FileLineData.linereport)
end

#===============================================================================
# Csv record reading/writing
#===============================================================================
def pbGetCsvRecord(rec,lineno,schema)
  record=[]
  repeat=false
  if schema[1][0,1]=="*"
    repeat=true
    start=1
  else
    repeat=false
    start=0
  end
  begin
    for i in start...schema[1].length
      chr=schema[1][i,1]
      case chr
      when "u"
        record.push(csvPosInt!(rec,lineno))
      when "v"
        field=csvPosInt!(rec,lineno)
        raise _INTL("Field '{1}' must be greater than 0\r\n{2}",field,FileLineData.linereport) if field==0
        record.push(field)
      when "i"
        record.push(csvInt!(rec,lineno))
      when "U", "I"
        field=csvfield!(rec)
        if field==""
          record.push(nil)
        elsif !field[/^\d+$/]
          raise _INTL("Field '{1}' must be 0 or greater\r\n{2}",field,FileLineData.linereport)
        else
          record.push(field.to_i)
        end
      when "x"
        field=csvfield!(rec)     
        if !field[/^[A-Fa-f0-9]+$/]
          raise _INTL("Field '{1}' is not a hexadecimal number\r\n{2}",field,FileLineData.linereport)
        end
        record.push(field.hex)
      when "s"
        record.push(csvfield!(rec))
      when "S"
        field=csvfield!(rec)
        if field==""
          record.push(nil)
        else
          record.push(field)
        end
      when "n" # Name
        field=csvfield!(rec)
        if !field[/^(?![0-9])\w+$/]
          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)
        end
        record.push(field)
      when "N" # Optional name
        field=csvfield!(rec)
        if field==""
          record.push(nil)
        else
          if !field[/^(?![0-9])\w+$/]
            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)
          end
          record.push(field)
        end
      when "b"
        record.push(csvBoolean!(rec,lineno))
      when "e"
        record.push(csvEnumField!(rec,schema[2+i-start],"",FileLineData.linereport))
      end
    end
    break if repeat && rec==""
  end while repeat
  return (schema[1].length==1) ? record[0] : record
end

def pbWriteCsvRecord(record,file,schema)
  if !record.is_a?(Array)
    rec=[record]
  else
    rec=record.clone
  end
  for i in 0...schema[1].length
    chr=schema[1][i,1]
    file.write(",") if i>0 
    if rec[i].nil?
      # do nothing
    elsif rec[i].is_a?(String)
      file.write(csvquote(rec[i]))
    elsif rec[i]==true
      file.write("true")
    elsif rec[i]==false
      file.write("false")
    elsif rec[i].is_a?(Numeric)
      case chr
      when "e"
        enumer=schema[2+i]
        if enumer.is_a?(Array)
          file.write(enumer[rec[i]])
        elsif enumer.is_a?(Symbol) || enumer.is_a?(String)
          mod=Object.const_get(enumer.to_sym)
          if enumer.to_s=="PBTrainers" && !mod.respond_to?("getCount")
            file.write((getConstantName(mod,rec[i]) rescue pbGetTrainerConst(rec[i])))
          else
            file.write(getConstantName(mod,rec[i]))
          end
        elsif enumer.is_a?(Module)
          file.write(getConstantName(enumer,rec[i]))
        elsif enumer.is_a?(Hash)
          for key in enumer.keys
            if enumer[key]==rec[i]
              file.write(key)
              break
            end
          end
        end
      else
        file.write(rec[i].inspect)
      end
    else
      file.write(rec[i].inspect)
    end
  end
  return record
end

#===============================================================================
# Encoding and decoding
#===============================================================================
def intSize(value)
  return 1 if value<0x80
  return 2 if value<0x4000
  return 3 if value<0x200000
  return 4 if value<0x10000000
  return 5
end

def encodeInt(strm,value)
  num=0
  loop do
    if value<0x80
      strm.fputb(value)
      return num+1
    end
    strm.fputb(0x80|(value&0x7F))
    value>>=7
    num+=1
  end
end

def decodeInt(strm)
  bits=0
  curbyte=0
  ret=0
  begin
    curbyte=strm.fgetb
    ret+=(curbyte&0x7F)<<bits
    bits+=7
  end while(((curbyte&0x80)>0)&&bits<0x1d)
  return ret
end

def strSize(str)
  return str.length+intSize(str.length)
end

def encodeString(strm,str)
  encodeInt(strm,str.length)
  strm.write(str)
end

def decodeString(strm)
  len=decodeInt(strm)
  return strm.read(len)
end

def strsplit(str,re)
  ret=[]
  tstr=str
  while re=~tstr
    ret[ret.length]=$~.pre_match
    tstr=$~.post_match
  end
  ret[ret.length]=tstr if ret.length
  return ret
end

def canonicalize(c)
  csplit=strsplit(c,/[\/\\]/)
  pos=-1
  ret=[]
  retstr=""
  for x in csplit
    if x=="."
    elsif x==".."
      ret.delete_at(pos) if pos>=0
      pos-=1
    else
      ret.push(x)
      pos+=1
    end
  end
  for i in 0...ret.length
    retstr+="/" if i>0
    retstr+=ret[i]
  end
  return retstr
end

def frozenArrayValue(arr)
  typestring=""
  for i in 0...arr.length
    if i>0
      typestring+=((i%20)==0) ? ",\r\n" : ","
    end
    typestring+=arr[i].to_s
  end
  return "["+typestring+"].freeze"
end

#===============================================================================
# Enum const manipulators and parsers
#===============================================================================
def pbGetConst(mod,item,err)
  isdef=false
  begin
    isdef=mod.const_defined?(item.to_sym)
  rescue
    raise sprintf(err,item)
  end
  raise sprintf(err,item) if !isdef
  return mod.const_get(item.to_sym)
end

def removeConstantValue(mod,value)
  for c in mod.constants
    if mod.const_get(c.to_sym)==value
      mod.send(:remove_const,c.to_sym)
    end
  end
end

def setConstantName(mod,value,name)
  for c in mod.constants
    if mod.const_get(c.to_sym)==value
      mod.send(:remove_const,c.to_sym)
    end
  end
  mod.const_set(name,value)
end

def getConstantName(mod,value)
  for c in mod.constants
    return c if mod.const_get(c.to_sym)==value
  end
  raise _INTL("Value {1} not defined by a constant in {2}",value,mod.name)
end

def parseItem(item)
  clonitem=item.upcase
  clonitem.sub!(/^\s*/){}
  clonitem.sub!(/\s*$/){}
  return pbGetConst(PBItems,clonitem,
     _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}",
     FileLineData.linereport))
end

def parseSpecies(item)
  clonitem=item.upcase
  clonitem.gsub!(/^[\s\n]*/){}
  clonitem.gsub!(/[\s\n]*$/){}
  clonitem="NIDORANmA" if clonitem=="NIDORANMA"
  clonitem="NIDORANfE" if clonitem=="NIDORANFE"
  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))
end

def parseMove(item)
  clonitem=item.upcase
  clonitem.sub!(/^\s*/){}
  clonitem.sub!(/\s*$/){}
  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))
end

def parseNature(item)
  clonitem=item.upcase
  clonitem.sub!(/^\s*/){}
  clonitem.sub!(/\s*$/){}
  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))
end

def parseTrainer(item)
  clonitem=item.clone
  clonitem.sub!(/^\s*/){}
  clonitem.sub!(/\s*$/){}
  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))
end

#===============================================================================
# Scripted constants
#===============================================================================
def pbFindScript(a,name)
  a.each{|i| 
     next if !i
     return i if i[1]==name
  }
  return nil
end

def pbAddScript(script,sectionname)
  begin
    scripts=load_data("Data/Constants.rxdata")
    scripts=[] if !scripts
  rescue
    scripts=[]
  end
  s=pbFindScript(scripts,sectionname)
  if s
    s[2]=Zlib::Deflate.deflate("#{script}\r\n")
  else
    scripts.push([rand(100000000),sectionname,Zlib::Deflate.deflate("#{script}\r\n")])
  end
  save_data(scripts,"Data/Constants.rxdata")
end



#===============================================================================
# Serial record
#===============================================================================
class SerialRecord < Array
  def bytesize
    return SerialRecord.bytesize(self)
  end

  def encode(strm)
    return SerialRecord.encode(self,strm)
  end

  def self.bytesize(arr)
    ret=0
    return 0 if !arr
    for field in arr
      if field==nil || field==true || field==false
        ret+=1
      elsif field.is_a?(String)
        ret+=strSize(field)+1
      elsif field.is_a?(Numeric)
        ret+=intSize(field)+1
      end
    end
    return ret
  end

  def self.encode(arr,strm)
    return if !arr
    for field in arr
      if field==nil
        strm.write("0")
      elsif field==true
        strm.write("T")
      elsif field==false
        strm.write("F")
      elsif field.is_a?(String)
        strm.write("\"")
        encodeString(strm,field)
      elsif field.is_a?(Numeric)
        strm.write("i")
        encodeInt(strm,field)
      end
    end
  end

  def self.decode(strm,offset,length)
    ret=SerialRecord.new
    strm.pos=offset
    while strm.pos<offset+length
      datatype=strm.read(1)
      case datatype
      when "0"
        ret.push(nil)
      when "T"
        ret.push(true)
      when "F"
        ret.push(false)
      when "\""
        ret.push(decodeString(strm))
      when "i"
        ret.push(decodeInt(strm))
      end
    end
    return ret
  end
end



def readSerialRecords(filename)
  ret=[]
  if !pbRgssExists?(filename)
    return ret
  end
  pbRgssOpen(filename,"rb"){|file|
     numrec=file.fgetdw>>3
     curpos=0
     for i in 0...numrec
       file.pos=curpos
       offset=file.fgetdw
       length=file.fgetdw
       record=SerialRecord.decode(file,offset,length)
       ret.push(record)
       curpos+=8
     end
  }
  return ret
end

def writeSerialRecords(filename,records)
  File.open(filename,"wb"){|file|
     totalsize=records.length*8
     for record in records
       file.fputdw(totalsize)
       bytesize=record.bytesize
       file.fputdw(bytesize)
       totalsize+=bytesize
     end
     for record in records
       record.encode(file)
     end
  }
end



#===============================================================================
# Data structures
#===============================================================================
class ByteArray
  include Enumerable

  def initialize(data=nil)
    @a=(data) ? data.unpack("C*") : []
  end

  def []=(i,value)
    @a[i]=value
  end

  def [](i)
    return @a[i]
  end

  def length; @a.length; end
  def size; @a.size; end

  def fillNils(length,value)
    for i in 0...length
      @a[i]=value if !@a[i]
    end
  end

  def each
    @a.each {|i| yield i}
  end

  def self._load(str)
    return self.new(str)
  end

  def _dump(depth=100)
    return @a.pack("C*")
  end
end



class WordArray
  include Enumerable

  def initialize(data=nil)
    @a=(data) ? data.unpack("v*") : []
  end

  def []=(i,value)
    @a[i]=value
  end

  def [](i)
    return @a[i]
  end

  def length; @a.length; end
  def size; @a.size; end

  def fillNils(length,value)
    for i in 0...length
      @a[i]=value if !@a[i]
    end
  end

  def each
    @a.each {|i| yield i}
  end

  def self._load(str)
    return self.new(str)
  end

  def _dump(depth=100)
    return @a.pack("v*")
  end
end



class SignedWordArray
  include Enumerable

  def initialize(data=nil)
    @a=(data) ? data.unpack("v*") : []
  end

  def []=(i,value)
    @a[i]=value
  end

  def [](i)
    v=@a[i]
    return v<0x8000 ? v : -((~v)&0xFFFF)-1
  end

  def length; @a.length; end
  def size; @a.size; end

  def fillNils(length,value)
    for i in 0...length
      @a[i]=value if !@a[i]
    end
  end

  def each
    @a.each {|i| yield i}
  end

  def self._load(str)
    return self.new(str)
  end

  def _dump(depth=100)
    return @a.pack("v*")
  end
end



#===============================================================================
# Compile types
#===============================================================================
def pbWriteDefaultTypes
  if !safeExists?("PBS/types.txt")
    File.open("PBS/types.txt","w"){|f|
       f.write(0xEF.chr)
       f.write(0xBB.chr)
       f.write(0xBF.chr)
fx=<<END
[0]
Name=Normal
InternalName=NORMAL
Weaknesses=FIGHTING
Immunities=GHOST

[1]
Name=Fighting
InternalName=FIGHTING
Weaknesses=FLYING,PSYCHIC
Resistances=ROCK,BUG,DARK

[2]
Name=Flying
InternalName=FLYING
Weaknesses=ROCK,ELECTRIC,ICE
Resistances=FIGHTING,BUG,GRASS
Immunities=GROUND

[3]
Name=Poison
InternalName=POISON
Weaknesses=GROUND,PSYCHIC
Resistances=FIGHTING,POISON,BUG,GRASS

[4]
Name=Ground
InternalName=GROUND
Weaknesses=WATER,GRASS,ICE
Resistances=POISON,ROCK
Immunities=ELECTRIC

[5]
Name=Rock
InternalName=ROCK
Weaknesses=FIGHTING,GROUND,STEEL,WATER,GRASS
Resistances=NORMAL,FLYING,POISON,FIRE

[6]
Name=Bug
InternalName=BUG
Weaknesses=FLYING,ROCK,FIRE
Resistances=FIGHTING,GROUND,GRASS

[7]
Name=Ghost
InternalName=GHOST
Weaknesses=GHOST,DARK
Resistances=POISON,BUG
Immunities=NORMAL,FIGHTING

[8]
Name=Steel
InternalName=STEEL
Weaknesses=FIGHTING,GROUND,FIRE
Resistances=NORMAL,FLYING,ROCK,BUG,GHOST,STEEL,GRASS,PSYCHIC,ICE,DRAGON,DARK
Immunities=POISON

[9]
Name=???
InternalName=QMARKS
IsPseudoType=true

[10]
Name=Fire
InternalName=FIRE
IsSpecialType=true
Weaknesses=GROUND,ROCK,WATER
Resistances=BUG,STEEL,FIRE,GRASS,ICE

[11]
Name=Water
InternalName=WATER
IsSpecialType=true
Weaknesses=GRASS,ELECTRIC
Resistances=STEEL,FIRE,WATER,ICE

[12]
Name=Grass
InternalName=GRASS
IsSpecialType=true
Weaknesses=FLYING,POISON,BUG,FIRE,ICE
Resistances=GROUND,WATER,GRASS,ELECTRIC

[13]
Name=Electric
InternalName=ELECTRIC
IsSpecialType=true
Weaknesses=GROUND
Resistances=FLYING,STEEL,ELECTRIC

[14]
Name=Psychic
InternalName=PSYCHIC
IsSpecialType=true
Weaknesses=BUG,GHOST,DARK
Resistances=FIGHTING,PSYCHIC

[15]
Name=Ice
InternalName=ICE
IsSpecialType=true
Weaknesses=FIGHTING,ROCK,STEEL,FIRE
Resistances=ICE

[16]
Name=Dragon
InternalName=DRAGON
IsSpecialType=true
Weaknesses=ICE,DRAGON
Resistances=FIRE,WATER,GRASS,ELECTRIC

[17]
Name=Dark
InternalName=DARK
IsSpecialType=true
Weaknesses=FIGHTING,BUG
Resistances=GHOST,DARK
Immunities=PSYCHIC

END
       f.write(fx)
    }
  end
end

def pbCompileTypes
  pbWriteDefaultTypes
  sections=[]
  typechart=[]
  types=[]
  nameToType={}
  requiredtypes={
     "Name"=>[1,"s"],
     "InternalName"=>[2,"s"],
  }
  optionaltypes={
     "IsPseudoType"=>[3,"b"],
     "IsSpecialType"=>[4,"b"],
     "Weaknesses"=>[5,"*s"],
     "Resistances"=>[6,"*s"],
     "Immunities"=>[7,"*s"]
  }
  currentmap=-1
  foundtypes=[]
  pbCompilerEachCommentedLine("PBS/types.txt") {|line,lineno|
     if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
       sectionname=$~[1]
       if currentmap>=0
         for reqtype in requiredtypes.keys
           if !foundtypes.include?(reqtype)
             raise _INTL("Required value '{1}' not given in section '{2}'\r\n{3}",reqtype,currentmap,FileLineData.linereport)
           end
         end
         foundtypes.clear
       end
       currentmap=sectionname.to_i
       types[currentmap]=[currentmap,nil,nil,false,false,[],[],[]]
     else
       if currentmap<0
         raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
       end
       if !line[/^\s*(\w+)\s*=\s*(.*)$/]
         raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
       end
       matchData=$~
       schema=nil
       FileLineData.setSection(currentmap,matchData[1],matchData[2])
       if requiredtypes.keys.include?(matchData[1])
         schema=requiredtypes[matchData[1]]
         foundtypes.push(matchData[1])
       else
         schema=optionaltypes[matchData[1]]
       end
       if schema
         record=pbGetCsvRecord(matchData[2],lineno,schema)
         types[currentmap][schema[0]]=record
       end
     end
  }
  types.compact!
  maxValue=0
  for type in types; maxValue=[maxValue,type[0]].max; end
  pseudotypes=[]
  specialtypes=[]
  typenames=[]
  typeinames=[]
  typehash={}
  for type in types
    pseudotypes.push(type[0]) if type[3]
    typenames[type[0]]=type[1]
    typeinames[type[0]]=type[2]
    typehash[type[0]]=type
  end
  for type in types
    n=type[1]
    for w in type[5]; if !typeinames.include?(w)
      raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Weaknesses)",w,n)
    end; end
    for w in type[6]; if !typeinames.include?(w)
      raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Resistances)",w,n)
    end; end
    for w in type[7]; if !typeinames.include?(w)
      raise _INTL("'{1}' is not a defined type (PBS/types.txt, {2}, Immunities)",w,n)
    end; end
  end
  for i in 0..maxValue
    pseudotypes.push(i) if !typehash[i]
  end
  pseudotypes.sort!
  for type in types; specialtypes.push(type[0]) if type[4]; end
  specialtypes.sort!
  MessageTypes.setMessages(MessageTypes::Types,typenames)
  code="class PBTypes\r\n"
  for type in types
    code+="#{type[2]}=#{type[0]}\r\n"
  end
  code+="def PBTypes.getName(id)\r\nreturn pbGetMessage(MessageTypes::Types,id)\r\nend\r\n"
  code+="def PBTypes.getCount; return #{types.length}; end\r\n"
  code+="def PBTypes.maxValue; return #{maxValue}; end\r\n"
  count=maxValue+1
  for i in 0...count
    type=typehash[i]
    j=0; k=i; while j<count
      typechart[k]=2
      atype=typehash[j]
      if type && atype
        typechart[k]=4 if type[5].include?(atype[2]) # weakness
        typechart[k]=1 if type[6].include?(atype[2]) # resistance
        typechart[k]=0 if type[7].include?(atype[2]) # immune
      end
      j+=1
      k+=count
    end
  end
  code+="end\r\n"
  eval(code)
  save_data([pseudotypes,specialtypes,typechart],"Data/types.dat")
  pbAddScript(code,"PBTypes")
  Graphics.update
end

#===============================================================================
# Compile town map points
#===============================================================================
def pbCompileTownMap
  nonglobaltypes={
     "Name"=>[0,"s"],
     "Filename"=>[1,"s"],
     "Point"=>[2,"uussUUUU"]
  }
  currentmap=-1
  rgnnames=[]
  placenames=[]
  placedescs=[]
  sections=[]
  pbCompilerEachCommentedLine("PBS/townmap.txt"){|line,lineno|
     if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
       currentmap=$~[1].to_i
       sections[currentmap]=[]
     else
       if currentmap<0
         raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
       end
       if !line[/^\s*(\w+)\s*=\s*(.*)$/]
         raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
       end
       settingname=$~[1]
       schema=nonglobaltypes[settingname]
       if schema
         record=pbGetCsvRecord($~[2],lineno,schema)
         if settingname=="Name"
           rgnnames[currentmap]=record
         elsif settingname=="Point"
           placenames.push(record[2])
           placedescs.push(record[3])
           sections[currentmap][schema[0]]=[] if !sections[currentmap][schema[0]]
           sections[currentmap][schema[0]].push(record)
         else   # Filename
           sections[currentmap][schema[0]]=record
         end
       end
     end
  }
  File.open("Data/townmap.dat","wb"){|f|
     Marshal.dump(sections,f)
  }
  MessageTypes.setMessages(
     MessageTypes::RegionNames,rgnnames
  )
  MessageTypes.setMessagesAsHash(
     MessageTypes::PlaceNames,placenames
  )
  MessageTypes.setMessagesAsHash(
     MessageTypes::PlaceDescriptions,placedescs
  )
end

#===============================================================================
# Compile map connections
#===============================================================================
def pbCompileConnections
  records=[]
  constants=""
  itemnames=[]
  pbCompilerEachPreppedLine("PBS/connections.txt"){|line,lineno|
     hashenum={
        "N"=>"N","North"=>"N",
        "E"=>"E","East"=>"E",
        "S"=>"S","South"=>"S",
        "W"=>"W","West"=>"W"
     }
     record=[]
     thisline=line.dup
     record.push(csvInt!(thisline,lineno))
     record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
     record.push(csvInt!(thisline,lineno))
     record.push(csvInt!(thisline,lineno))
     record.push(csvEnumFieldOrInt!(thisline,hashenum,"",sprintf("(line %d)",lineno)))
     record.push(csvInt!(thisline,lineno))          
     if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[0])) &&
        !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[0]))
       print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[0],FileLineData.linereport)
     end
     if !pbRgssExists?(sprintf("Data/Map%03d.rxdata",record[3])) &&
        !pbRgssExists?(sprintf("Data/Map%03d.rvdata",record[3]))
       print _INTL("Warning: Map {1}, as mentioned in the map\r\nconnection data, was not found.\r\n{2}",record[3],FileLineData.linereport)
     end
     case record[1]
     when "N"
       raise _INTL("North side of first map must connect with south side of second map\r\n{1}",FileLineData.linereport) if record[4]!="S"
     when "S"
       raise _INTL("South side of first map must connect with north side of second map\r\n{1}",FileLineData.linereport) if record[4]!="N"
     when "E"
       raise _INTL("East side of first map must connect with west side of second map\r\n{1}",FileLineData.linereport) if record[4]!="W"
     when "W"
       raise _INTL("West side of first map must connect with east side of second map\r\n{1}",FileLineData.linereport) if record[4]!="E"
     end
     records.push(record)
  }
  save_data(records,"Data/connections.dat")
  Graphics.update
end

#===============================================================================
# Compile abilities
#===============================================================================
def pbCompileAbilities
  records=[]
  movenames=[]
  movedescs=[]
  maxValue=0
  pbCompilerEachPreppedLine("PBS/abilities.txt"){|line,lineno|
     record=pbGetCsvRecord(line,lineno,[0,"vnss"])
     movenames[record[0]]=record[2]
     movedescs[record[0]]=record[3]
     maxValue=[maxValue,record[0]].max
     records.push(record)
  }
  MessageTypes.setMessages(MessageTypes::Abilities,movenames)
  MessageTypes.setMessages(MessageTypes::AbilityDescs,movedescs)
  code="class PBAbilities\r\n"
  for rec in records
    code+="#{rec[1]}=#{rec[0]}\r\n"
  end
  code+="\r\ndef PBAbilities.getName(id)\r\nreturn pbGetMessage(MessageTypes::Abilities,id)\r\nend"
  code+="\r\ndef PBAbilities.getCount\r\nreturn #{records.length}\r\nend\r\n"
  code+="\r\ndef PBAbilities.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBAbilities")
end

#===============================================================================
# Compile move data
#===============================================================================
class PBMoveDataOld
  attr_reader :function,:basedamage,:type,:accuracy
  attr_reader :totalpp,:addlEffect,:target,:priority
  attr_reader :flags
  attr_reader :category,:contestType #~~ Pokémon Contests ~~ Required

  def initialize(moveid)
    movedata=pbRgssOpen("Data/rsattacks.dat")
    movedata.pos=moveid*9
    @function=movedata.fgetb
    @basedamage=movedata.fgetb
    @type=movedata.fgetb
    @accuracy=movedata.fgetb
    @totalpp=movedata.fgetb
    @addlEffect=movedata.fgetb
    @target=movedata.fgetb
    @priority=movedata.fgetsb
    @flags=movedata.fgetb
    movedata.close
  end

  def category
    return 2 if @basedamage==0
    return @type<10 ? 0 : 1
  end
end

def pbCompileMoves
  records=[]
  movenames=[]
  movedescs=[]
  movedata=[]
  maxValue=0
  pbCompilerEachPreppedLine("PBS/moves.txt"){|line,lineno|
     thisline=line.clone
     record=[]
     flags=0
     #~~ Pokémon Contests ~~ Required
     begin
       record=pbGetCsvRecord(line,lineno,[0,"vnsxueeuuuxises",
          nil,nil,nil,nil,nil,PBTypes,["Physical","Special","Status"],
          nil,nil,nil,nil,nil,nil,["Cool","Beauty","Cute","Smart","Tough"],nil
       ])
       #~~
       pbCheckWord(record[3],_INTL("Function code"))
       flags|=1 if record[12][/a/]
       flags|=2 if record[12][/b/]
       flags|=4 if record[12][/c/]
       flags|=8 if record[12][/d/]
       flags|=16 if record[12][/e/]
       flags|=32 if record[12][/f/]
       flags|=64 if record[12][/g/]
       flags|=128 if record[12][/h/]
       flags|=256 if record[12][/i/]
       flags|=512 if record[12][/j/]
       flags|=1024 if record[12][/k/]
       flags|=2048 if record[12][/l/]
       flags|=4096 if record[12][/m/]
       flags|=8192 if record[12][/n/]
       flags|=16384 if record[12][/o/]
       flags|=32768 if record[12][/p/]
     rescue
       oldmessage=$!.message
       raise if !pbRgssExists?("Data/rsattacks.dat")
       begin
         oldrecord=pbGetCsvRecord(thisline,lineno,[0,"unss",nil,nil,nil,nil])
       rescue
         raise $!.message+"\r\n"+oldmessage
       end
       oldmovedata=PBMoveDataOld.new(oldrecord[0])
       flags=oldmovedata.flags
       record=[oldrecord[0],oldrecord[1],oldrecord[2],
          oldmovedata.function,
          oldmovedata.basedamage,
          oldmovedata.type,
          oldmovedata.category,
          oldmovedata.accuracy,
          oldmovedata.totalpp,
          oldmovedata.addlEffect,
          oldmovedata.target,
          oldmovedata.priority,
          oldmovedata.flags,
          0, # No contest type defined
          oldrecord[3]]
     end
     pbCheckWord(record[3],_INTL("Function code"))
     pbCheckByte(record[4],_INTL("Base damage"))
     if record[6]==2 && record[4]!=0
       raise _INTL("Status moves must have a base damage of 0, use either Physical or Special\r\n{1}",FileLineData.linereport)
     end
     if record[6]!=2 && record[4]==0
       print _INTL("Warning: Physical and special moves can't have a base damage of 0, changing to a Status move\r\n{1}",FileLineData.linereport)
       record[6]=2
     end
     pbCheckByte(record[7],_INTL("Accuracy"))
     pbCheckByte(record[8],_INTL("Total PP"))
     pbCheckByte(record[9],_INTL("Additional Effect"))
     pbCheckWord(record[10],_INTL("Target"))
     pbCheckSignedByte(record[11],_INTL("Priority"))
     maxValue=[maxValue,record[0]].max
     movedata[record[0]]=[
        record[3],  # Function code
        record[4],  # Damage
        record[5],  # Type
        record[6],  # Category
        record[7],  # Accuracy
        record[8],  # Total PP
        record[9],  # Effect chance
        record[10], # Target
        record[11], # Priority
        flags,      # Flags
        record[13]  # Contest type #~~ Pokémon Contests ~~ Required
     ].pack("vCCCCCCvCvC")
     movenames[record[0]]=record[2]  # Name
     movedescs[record[0]]=record[14] # Description # Changed to 14
     records.push(record)
  }
  defaultdata=[0,0,0,0,0,0,0,0,0,0,0].pack("vCCCCCCvCvC")
  File.open("Data/moves.dat","wb"){|file|
     for i in 0...movedata.length
       file.write(movedata[i] ? movedata[i] : defaultdata)
     end
  }
  MessageTypes.setMessages(MessageTypes::Moves,movenames)
  MessageTypes.setMessages(MessageTypes::MoveDescriptions,movedescs)
  code="class PBMoves\r\n"
  for rec in records
    code+="#{rec[1]}=#{rec[0]}\r\n"
  end
  code+="\r\ndef PBMoves.getName(id)\r\nreturn pbGetMessage(MessageTypes::Moves,id)\r\nend"
  code+="\r\ndef PBMoves.getCount\r\nreturn #{records.length}\r\nend"
  code+="\r\ndef PBMoves.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBMoves")
end

#~~ Pokémon Contests ~~ Required
def pbCompileContestMoves
  records=[]
  contestmovenames=[]
  contestmovedescs=[]
  contestmovedata=[]
  maxValue=0
  haveRsAttacks=pbRgssExists?("Data/rsattacks.dat")
  pbCompilerEachPreppedLine("PBS/contestmoves.txt"){|line,lineno|
     thisline=line.clone
     record=[]
     flags=0

       record=pbGetCsvRecord(line,lineno,[0,"vnseUUUs",
          nil,nil,nil,["Cool","Beauty","Cute","Smart","Tough"],nil,nil,nil,nil
       ])
     
     maxValue=[maxValue,record[0]].max
     contestmovedata[record[0]]=[
        record[3],  # Contest Type
        record[4],  # Hearts
        record[5],  # Jam
        record[6]   # Function Code
     ].pack("CCCC")
     contestmovenames[record[0]]=record[2]  # Name
     contestmovedescs[record[0]]=record[7] # Description
     records.push(record)
     }
  defaultdata=[0,0,0,0].pack("CCCC")
  File.open("Data/contestmoves.dat","wb"){|file|
     for i in 0...contestmovedata.length
       file.write(contestmovedata[i] ? contestmovedata[i] : defaultdata)
     end
  }
  MessageTypes.setMessages(MessageTypes::ContestMoves,contestmovenames)
  MessageTypes.setMessages(MessageTypes::ContestMoveDescriptions,contestmovedescs)
  code="class PBContestMoves\r\n"
  for rec in records
    code+="#{rec[1]}=#{rec[0]}\r\n"
  end
  code+="\r\ndef self.getName(id)\r\nreturn pbGetMessage(MessageTypes::Moves,id)\r\nend"
  code+="\r\ndef self.getCount\r\nreturn #{records.length}\r\nend"
  code+="\r\ndef self.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBContestMoves")
end
#~~

#===============================================================================
# Compile items
#===============================================================================
class ItemList
  include Enumerable

  def initialize; @list=[]; end
  def length; @list.length; end
  def []=(x,v); @list[x]=v; end
 
  def [](x)
    if !@list[x]
      defrecord=SerialRecord.new
      defrecord.push(0)
      defrecord.push("????????")
      defrecord.push(0)
      defrecord.push(0)
      defrecord.push("????????")
      @list[x]=defrecord
      return defrecord
    end
    return @list[x]
  end

  def each
    for i in 0...self.length
      yield self[i]
    end
  end
end



def readItemList(filename)
  ret=ItemList.new
  if !pbRgssExists?(filename)
    return ret
  end
  pbRgssOpen(filename,"rb"){|file|
     numrec=file.fgetdw>>3
     curpos=0
     for i in 0...numrec
       file.pos=curpos
       offset=file.fgetdw
       length=file.fgetdw
       record=SerialRecord.decode(file,offset,length)
       ret[record[0]]=record
       curpos+=8
     end
  }
  return ret
end

def pbCompileItems
  records=[]
  constants=""
  itemnames=[]
  itempluralnames=[]
  itemdescs=[]
  maxValue=0
  pbCompilerEachCommentedLine("PBS/items.txt"){|line,lineno|
     linerecord=pbGetCsvRecord(line,lineno,[0,"vnssuusuuUN"])
     record=SerialRecord.new
     record[ITEMID]        = linerecord[0]
     constant=linerecord[1]
     constants+="#{constant}=#{record[0]}\r\n"
     record[ITEMNAME]      = linerecord[2]
     itemnames[record[0]]=linerecord[2]
     record[ITEMPLURAL]    = linerecord[3]
     itempluralnames[record[0]]=linerecord[3]
     record[ITEMPOCKET]    = linerecord[4]
     record[ITEMPRICE]     = linerecord[5]
     record[ITEMDESC]      = linerecord[6]
     itemdescs[record[0]]=linerecord[6]
     record[ITEMUSE]       = linerecord[7]
     record[ITEMBATTLEUSE] = linerecord[8]
     record[ITEMTYPE]      = linerecord[9]
     if linerecord[9]!="" && linerecord[10]
       record[ITEMMACHINE] = parseMove(linerecord[10])
     else
       record[ITEMMACHINE] = 0
     end
     maxValue=[maxValue,record[0]].max
     records.push(record)
  }
  MessageTypes.setMessages(MessageTypes::Items,itemnames)
  MessageTypes.setMessages(MessageTypes::ItemPlurals,itempluralnames)
  MessageTypes.setMessages(MessageTypes::ItemDescriptions,itemdescs)
  writeSerialRecords("Data/items.dat",records)
  code="class PBItems\r\n#{constants}"
  code+="\r\ndef PBItems.getName(id)\r\nreturn pbGetMessage(MessageTypes::Items,id)\r\nend\r\n"
  code+="\r\ndef PBItems.getNamePlural(id)\r\nreturn pbGetMessage(MessageTypes::ItemPlurals,id)\r\nend\r\n"
  code+="\r\ndef PBItems.getCount\r\nreturn #{records.length}\r\nend\r\n"
  code+="\r\ndef PBItems.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBItems")
  Graphics.update
end

#===============================================================================
# Compile berry plants
#===============================================================================
def pbCompileBerryPlants
  sections=[]
  if File.exists?("PBS/berryplants.txt")
    pbCompilerEachCommentedLine("PBS/berryplants.txt"){|line,lineno|
       if line[ /^([^=]+)=(.*)$/ ]
         key=$1
         value=$2
         value=value.split(",")
         for i in 0...value.length
           value[i].sub!(/^\s*/){}
           value[i].sub!(/\s*$/){}
           value[i]=value[i].to_i
         end
         item=parseItem(key)
         sections[item]=value
       end
    }
  end
  save_data(sections,"Data/berryplants.dat")
end

#===============================================================================
# Compile Pokémon
#===============================================================================
def pbCompilePokemonData
  # Free bytes: 0, 1, 17, 29, 30, 37, 56-75
  sections=[]
  requiredtypes={
     "Name"=>[0,"s"],
     "Kind"=>[0,"s"],
     "InternalName"=>[0,"c"],
     "Pokedex"=>[0,"S"],
     "Moves"=>[0,"*uE",nil,PBMoves],
     "Color"=>[6,"e",PBColors],
     "Type1"=>[8,"e",PBTypes],
     "BaseStats"=>[10,"uuuuuu"],
     "Rareness"=>[16,"u"],
     "GenderRate"=>[18,"e",{"AlwaysMale"=>0,"FemaleOneEighth"=>31,
        "Female25Percent"=>63,"Female50Percent"=>127,"Female75Percent"=>191,
        "FemaleSevenEighths"=>223,"AlwaysFemale"=>254,"Genderless"=>255}],
     "Happiness"=>[19,"u"],
     "GrowthRate"=>[20,"e",{"Medium"=>0,"MediumFast"=>0,"Erratic"=>1,
        "Fluctuating"=>2,"Parabolic"=>3,"MediumSlow"=>3,"Fast"=>4,"Slow"=>5}],
     "StepsToHatch"=>[21,"w"],
     "EffortPoints"=>[23,"uuuuuu"],
     "Compatibility"=>[31,"eg",PBEggGroups,PBEggGroups],
     "Height"=>[33,"f"],
     "Weight"=>[35,"f"],
     "BaseEXP"=>[38,"w"],
  }
  optionaltypes={
     "BattlerPlayerY"=>[0,"i"],
     "BattlerEnemyY"=>[0,"i"],
     "BattlerAltitude"=>[0,"i"],
     "EggMoves"=>[0,"*E",PBMoves],
     "FormNames"=>[0,"S"],
     "RegionalNumbers"=>[0,"*w"],
     "Evolutions"=>[0,"*ses",nil,PBEvolution],
     "Abilities"=>[2,"EG",PBAbilities,PBAbilities],
     "Habitat"=>[7,"e",["","Grassland","Forest","WatersEdge","Sea","Cave","Mountain","RoughTerrain","Urban","Rare"]],
     "Type2"=>[9,"e",PBTypes],
     "HiddenAbility"=>[40,"EGGG",PBAbilities,PBAbilities,PBAbilities,PBAbilities],
     "WildItemCommon"=>[48,"E",PBItems],
     "WildItemUncommon"=>[50,"E",PBItems],
     "WildItemRare"=>[52,"E",PBItems],
     "Incense"=>[54,"E",PBItems]
  }
  currentmap=-1
  dexdatas=[]
  eggmoves=[]
  entries=[]
  kinds=[]
  speciesnames=[]
  moves=[]
  evolutions=[]
  regionals=[]
  formnames=[]
  metrics=[SignedWordArray.new,SignedWordArray.new,SignedWordArray.new]
  constants=""
  maxValue=0
  File.open("PBS/pokemon.txt","rb"){|f|
     FileLineData.file="PBS/pokemon.txt"
     pbEachFileSection(f){|lastsection,currentmap|
        dexdata=[]
        for i in 0...76
          dexdata[i]=0
        end
        thesemoves=[]
        theseevos=[]
        if !lastsection["Type2"] || lastsection["Type2"]==""
          if !lastsection["Type1"] || lastsection["Type1"]==""
            raise _INTL("No Pokémon type is defined in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
            next
          end
          lastsection["Type2"]=lastsection["Type1"].clone
        end
        [requiredtypes,optionaltypes].each{|hash|
           for key in hash.keys
             FileLineData.setSection(currentmap,key,lastsection[key])
             maxValue=[maxValue,currentmap].max
             sectionDisplay=currentmap.to_s
             next if hash[key][0]<0
             if currentmap==0
               raise _INTL("A Pokemon species can't be numbered 0 (PBS/pokemon.txt)")
             end
             if !lastsection[key] || lastsection[key]==""
               raise _INTL("Required entry {1} is missing or empty in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
               next
             end
             secvalue=lastsection[key]
             rtschema=hash[key]
             schema=hash[key][1]
             valueindex=0
             loop do
               offset=0
               for i in 0...schema.length
                 next if schema[i,1]=="*"
                 minus1=(schema[0,1]=="*") ? -1 : 0
                 if (schema[i,1]=="g" || schema[i,1]=="G") && secvalue==""
                   if key=="Compatibility"
                     dexdata[rtschema[0]+offset]=dexdata[rtschema[0]]
                   end
                   break
                 end
                 case schema[i,1]
                 when "e", "g"
                   value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
                   bytes=1
                 when "E", "G"
                   value=csvEnumField!(secvalue,rtschema[2+i+minus1],key,sectionDisplay)
                   bytes=2
                 when "i"
                   value=csvInt!(secvalue,key)
                   bytes=1
                 when "u"
                   value=csvPosInt!(secvalue,key)
                   bytes=1
                 when "w"
                   value=csvPosInt!(secvalue,key)
                   bytes=2
                 when "f"
                   value=csvFloat!(secvalue,key,sectionDisplay)
                   value=(value*10).round
                   if value<=0
                     raise _INTL("Value '{1}' can't be less than or close to 0 (section {2}, PBS/pokemon.txt)",key,currentmap)
                   end
                   bytes=2
                 when "c", "s"
                   value=csvfield!(secvalue)
                 when "S"
                   value=secvalue
                   secvalue=""
                 end
                 if key=="EggMoves"
                   eggmoves[currentmap]=[] if !eggmoves[currentmap]
                   eggmoves[currentmap].push(value)
                 elsif key=="Moves"
                   thesemoves.push(value)
                 elsif key=="RegionalNumbers"
                   regionals[valueindex]=[] if !regionals[valueindex]
                   regionals[valueindex][currentmap]=value
                 elsif key=="Evolutions"
                   theseevos.push(value)
                 elsif key=="InternalName"
                   raise _INTL("Invalid internal name: {1} (section {2}, PBS/pokemon.txt)",value,currentmap) if !value[/^(?![0-9])\w*$/]
                   constants+="#{value}=#{currentmap}\r\n"
                 elsif key=="Kind"
                   raise _INTL("Kind {1} is greater than 20 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>20
                   kinds[currentmap]=value
                 elsif key=="Pokedex"
                   entries[currentmap]=value
                 elsif key=="BattlerPlayerY"
                   pbCheckSignedWord(value,key)
                   metrics[0][currentmap]=value
                 elsif key=="BattlerEnemyY"
                   pbCheckSignedWord(value,key)
                   metrics[1][currentmap]=value
                 elsif key=="BattlerAltitude"
                   pbCheckSignedWord(value,key)
                   metrics[2][currentmap]=value
                 elsif key=="Name"
                   raise _INTL("Species name {1} is greater than 20 characters long (section {2}, PBS/pokemon.txt)",value,currentmap) if value.length>20
                   speciesnames[currentmap]=value
                 elsif key=="FormNames"
                   formnames[currentmap]=value
                 else
                   dexdata[rtschema[0]+offset]=value&0xFF
                   dexdata[rtschema[0]+1+offset]=(value>>8)&0xFF if bytes>1
                   offset+=bytes
                 end
                 valueindex+=1
               end
               break if secvalue==""
               break if schema[0,1]!="*"
             end
           end
        }
        movelist=[]
        evolist=[]
        for i in 0...thesemoves.length/2
          movelist.push([thesemoves[i*2],thesemoves[i*2+1],i])
        end
        movelist.sort!{|a,b| a[0]==b[0] ? a[2]<=>b[2] : a[0]<=>b[0]}
        for i in movelist; i.pop; end
        for i in 0...theseevos.length/3
          evolist.push([theseevos[i*3],theseevos[i*3+1],theseevos[i*3+2]])
        end
        moves[currentmap]=movelist
        evolutions[currentmap]=evolist
        dexdatas[currentmap]=dexdata
     }
  }
  if dexdatas.length==0
    raise _INTL("No Pokémon species are defined in pokemon.txt")
  end
  count=dexdatas.compact.length
  code="module PBSpecies\r\n#{constants}"
  for i in 0...speciesnames.length
    speciesnames[i]="????????" if !speciesnames[i]
  end
  code+="def PBSpecies.getName(id)\r\nreturn pbGetMessage(MessageTypes::Species,id)\r\nend\r\n"
  code+="def PBSpecies.getCount\r\nreturn #{count}\r\nend\r\n"
  code+="def PBSpecies.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBSpecies")
  for e in 0...evolutions.length
    evolist=evolutions[e]
    next if !evolist
    for i in 0...evolist.length
      FileLineData.setSection(i,"Evolutions","")
      evonib=evolist[i][1]
      evolist[i][0]=csvEnumField!(evolist[i][0],PBSpecies,"Evolutions",i)
      case PBEvolution::EVOPARAM[evonib]
      when 1
        evolist[i][2]=csvPosInt!(evolist[i][2])
      when 2
        evolist[i][2]=csvEnumField!(evolist[i][2],PBItems,"Evolutions",i)
      when 3
        evolist[i][2]=csvEnumField!(evolist[i][2],PBMoves,"Evolutions",i)
      when 4
        evolist[i][2]=csvEnumField!(evolist[i][2],PBSpecies,"Evolutions",i)
      when 5
        evolist[i][2]=csvEnumField!(evolist[i][2],PBTypes,"Evolutions",i)
      else
        evolist[i][2]=0
      end
      evolist[i][3]=0
    end
  end
  _EVODATAMASK=0xC0
  _EVONEXTFORM=0x00
  _EVOPREVFORM=0x40
  for e in 0...evolutions.length
    evolist=evolutions[e]
    next if !evolist
    parent=nil
    child=-1
    for f in 0...evolutions.length
      evolist=evolutions[f]
      next if !evolist || e==f
      for g in evolist
        if g[0]==e && (g[3]&_EVODATAMASK)==_EVONEXTFORM
          parent=g
          child=f
          break
        end
      end
      break if parent
    end
    if parent
      evolutions[e]=[[child,parent[1],parent[2],_EVOPREVFORM]].concat(evolutions[e])
    end
  end
  metrics[0].fillNils(dexdatas.length,0) # player Y
  metrics[1].fillNils(dexdatas.length,0) # enemy Y
  metrics[2].fillNils(dexdatas.length,0) # altitude
  save_data(metrics,"Data/metrics.dat")
  File.open("Data/regionals.dat","wb"){|f|
     f.fputw(regionals.length)
     f.fputw(dexdatas.length)
     for i in 0...regionals.length
       for j in 0...dexdatas.length
         num=regionals[i][j]
         num=0 if !num
         f.fputw(num)
       end
     end
  }
  File.open("Data/evolutions.dat","wb"){|f|
     mx=[maxValue,evolutions.length-1].max
     offset=mx*8
     for i in 1..mx
       f.fputdw(offset)
       f.fputdw(evolutions[i] ? evolutions[i].length*5 : 0)
       offset+=evolutions[i] ? evolutions[i].length*5 : 0
     end
     for i in 1..mx
       next if !evolutions[i]
       for j in evolutions[i]
         f.fputb(j[3]|j[1])
         f.fputw(j[2])
         f.fputw(j[0])
       end
     end
  }
  File.open("Data/dexdata.dat","wb"){|f|
     mx=[maxValue,dexdatas.length-1].max
     for i in 1..mx
       if dexdatas[i]
         dexdatas[i].each {|item| f.fputb(item)}
       else
         76.times { f.fputb(0) }
       end
     end
  }
  File.open("Data/eggEmerald.dat","wb"){|f|
     mx=[maxValue,eggmoves.length-1].max
     offset=mx*8
     for i in 1..mx
       f.fputdw(offset)
       f.fputdw(eggmoves[i] ? eggmoves[i].length : 0)
       offset+=eggmoves[i] ? eggmoves[i].length*2 : 0
     end
     for i in 1..mx
       next if !eggmoves[i]
       for j in eggmoves[i]
         f.fputw(j)
       end
     end
  }
  MessageTypes.setMessages(MessageTypes::Species,speciesnames)
  MessageTypes.setMessages(MessageTypes::Kinds,kinds)
  MessageTypes.setMessages(MessageTypes::Entries,entries)
  MessageTypes.setMessages(MessageTypes::FormNames,formnames)
  File.open("Data/attacksRS.dat","wb"){|f|
     mx=[maxValue,moves.length-1].max
     offset=mx*8
     for i in 1..mx
       f.fputdw(offset)
       f.fputdw(moves[i] ? moves[i].length*2 : 0)
       offset+=moves[i] ? moves[i].length*4 : 0
     end
     for i in 1..mx
       next if !moves[i]
       for j in moves[i]
         f.fputw(j[0])
         f.fputw(j[1])
       end
     end
  }
end

#===============================================================================
# Compile TM/TM/Move Tutor compatibilities
#===============================================================================
def pbTMRS   # Backup Gen 3 TM list
  rstm=[# TMs
        :FOCUSPUNCH,:DRAGONCLAW,:WATERPULSE,:CALMMIND,:ROAR,
        :TOXIC,:HAIL,:BULKUP,:BULLETSEED,:HIDDENPOWER,
        :SUNNYDAY,:TAUNT,:ICEBEAM,:BLIZZARD,:HYPERBEAM,
        :LIGHTSCREEN,:PROTECT,:RAINDANCE,:GIGADRAIN,:SAFEGUARD,
        :FRUSTRATION,:SOLARBEAM,:IRONTAIL,:THUNDERBOLT,:THUNDER,
        :EARTHQUAKE,:RETURN,:DIG,:PSYCHIC,:SHADOWBALL,
        :BRICKBREAK,:DOUBLETEAM,:REFLECT,:SHOCKWAVE,:FLAMETHROWER,
        :SLUDGEBOMB,:SANDSTORM,:FIREBLAST,:ROCKTOMB,:AERIALACE,
        :TORMENT,:FACADE,:SECRETPOWER,:REST,:ATTRACT,
        :THIEF,:STEELWING,:SKILLSWAP,:SNATCH,:OVERHEAT,
        # HMs
        :CUT,:FLY,:SURF,:STRENGTH,:FLASH,:ROCKSMASH,:WATERFALL,:DIVE]
  ret=[]
  for i in 0...rstm.length
    ret.push((parseMove(rstm.to_s) rescue 0))
  end
  return ret
end

def pbCompileMachines
  lineno=1
  havesection=false
  sectionname=nil
  sections=[]
  if safeExists?("PBS/tm.txt")
    f=File.open("PBS/tm.txt","rb")
    FileLineData.file="PBS/tm.txt"
    f.each_line {|line|
       if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
         line=line[3,line.length-3]
       end
       FileLineData.setLine(line,lineno)
       if !line[/^\#/] && !line[/^\s*$/]
         if line[/^\s*\[\s*(.*)\s*\]\s*$/]
           sectionname=parseMove($~[1])
           sections[sectionname]=WordArray.new
           havesection=true
         else
           if sectionname==nil
             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)
           end
           specieslist=line.sub(/\s+$/,"").split(",")
           for species in specieslist
             next if !species || species==""
             sec=sections[sectionname]
             sec[sec.length]=parseSpecies(species)
           end
         end
       end
       lineno+=1
       if lineno%500==0
         Graphics.update
       end
       if lineno%50==0
         Win32API.SetWindowText(_INTL("Processing line {1}",lineno))
       end
    }
    f.close
  elsif safeExists?("Data/tmRS.dat")
    tmrs=pbTMRS()
    for i in 0...58
      next if !tmrs[i] || tmrs[i]==0
      sections[tmrs[i]]=[]
    end
    File.open("Data/tmRS.dat","rb"){|f|
       species=1
       while !f.eof?
         data=f.read(8)+"\0\0\0\0\0\0\0\0"
         for i in 0...58
           next if !tmrs[i] || tmrs[i]==0
           if (data[i>>3]&(1<<(i&7)))!=0
             sections[tmrs[i]].push(species)
           end
         end
         species+=1
       end
    }
  end
  save_data(sections,"Data/tm.dat")
end

#===============================================================================
# Extract trainer types to PBS file, compile trainer types and individual trainers
#===============================================================================
def pbExtractTrainers
  trainertypes=nil
  pbRgssOpen("Data/trainertypes.dat","rb"){|f|
     trainertypes=Marshal.load(f)
  }
  return if !trainertypes
  File.open("trainertypes.txt","wb"){|f|
     f.write(0xEF.chr)
     f.write(0xBB.chr)
     f.write(0xBF.chr)
     for i in 0...trainertypes.length
       next if !trainertypes[i]
       record=trainertypes[i]
       begin
         cnst=getConstantName(PBTrainers,record[0])
       rescue
         next
       end
       f.write(sprintf("%d,%s,%s,%d,%s,%s,%s,%s\r\n",
          record[0],csvquote(cnst),csvquote(record[2]),
          record[3],csvquote(record[4]),csvquote(record[5]),csvquote(record[6]),
          record[7] ? ["Male","Female","Mixed"][record[7]] : "Mixed"
       ))
     end
  }
end

def pbCompileTrainers
  # Trainer types
  records=[]
  trainernames=[]
  count=0
  maxValue=0
  pbCompilerEachPreppedLine("PBS/trainertypes.txt"){|line,lineno|
     record=pbGetCsvRecord(line,lineno,[0,"unsUSSSeUs", # ID can be 0
        nil,nil,nil,nil,nil,nil,nil,{
        ""=>2,"Male"=>0,"M"=>0,"0"=>0,"Female"=>1,"F"=>1,"1"=>1,"Mixed"=>2,"X"=>2,"2"=>2
        },nil,nil]
     )
     if record[3] && (record[3]<0 || record[3]>255)
       raise _INTL("Bad money amount (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
     end
     record[3]=30 if !record[3]
     if record[8] && (record[8]<0 || record[8]>255)
       raise _INTL("Bad skill value (must be from 0 through 255)\r\n{1}",FileLineData.linereport)
     end
     record[8]=record[3] if !record[8]
     record[9]="" if !record[9]
     trainernames[record[0]]=record[2]
     if records[record[0]]
       raise _INTL("Two trainer types ({1} and {2}) have the same ID ({3}), which is not allowed.\r\n{4}",
          records[record[0]][1],record[1],record[0],FileLineData.linereport)
     end
     records[record[0]]=record
     maxValue=[maxValue,record[0]].max
  }
  count=records.compact.length
  MessageTypes.setMessages(MessageTypes::TrainerTypes,trainernames)
  code="class PBTrainers\r\n"
  for rec in records
    next if !rec
    code+="#{rec[1]}=#{rec[0]}\r\n"
  end
  code+="\r\ndef PBTrainers.getName(id)\r\nreturn pbGetMessage(MessageTypes::TrainerTypes,id)\r\nend"
  code+="\r\ndef PBTrainers.getCount\r\nreturn #{count}\r\nend"
  code+="\r\ndef PBTrainers.maxValue\r\nreturn #{maxValue}\r\nend\r\nend"
  eval(code)
  pbAddScript(code,"PBTrainers")
  File.open("Data/trainertypes.dat","wb"){|f|
     Marshal.dump(records,f)
  }
  # Individual trainers
  lines=[]
  linenos=[]
  lineno=1
  File.open("PBS/trainers.txt","rb"){|f|
     FileLineData.file="PBS/trainers.txt"
     f.each_line {|line|
        if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
          line=line[3,line.length-3]
        end
        line=prepline(line)
        if line!=""
          lines.push(line)
          linenos.push(lineno)
        end
        lineno+=1
     }
  }
  nameoffset=0
  trainers=[]
  trainernames.clear
  i=0; loop do break unless i<lines.length
    FileLineData.setLine(lines[i],linenos[i])
    trainername=parseTrainer(lines[i])
    FileLineData.setLine(lines[i+1],linenos[i+1])
    nameline=strsplit(lines[i+1],/\s*,\s*/)
    name=nameline[0]
    raise _INTL("Trainer name too long\r\n{1}",FileLineData.linereport) if name.length>=0x10000
    trainernames.push(name)
    partyid=0
    if nameline[1] && nameline[1]!=""
      raise _INTL("Expected a number for the trainer battle ID\r\n{1}",FileLineData.linereport) if !nameline[1][/^\d+$/]
      partyid=nameline[1].to_i
    end
    FileLineData.setLine(lines[i+2],linenos[i+2])
    items=strsplit(lines[i+2],/\s*,\s*/)
    items[0].gsub!(/^\s+/,"")   # Number of Pokémon
    raise _INTL("Expected a number for the number of Pokémon\r\n{1}",FileLineData.linereport) if !items[0][/^\d+$/]
    numpoke=items[0].to_i
    realitems=[]
    for j in 1...items.length   # Items held by Trainer
      realitems.push(parseItem(items[j])) if items[j] && items[j]!=""
    end
    pkmn=[]
    for j in 0...numpoke
      FileLineData.setLine(lines[i+j+3],linenos[i+j+3])
      poke=strsplit(lines[i+j+3],/\s*,\s*/)
      begin
        # Species
        poke[TPSPECIES]=parseSpecies(poke[TPSPECIES])
      rescue
        raise _INTL("Expected a species name: {1}\r\n{2}",poke[0],FileLineData.linereport)
      end
      # Level
      poke[TPLEVEL]=poke[TPLEVEL].to_i
      raise _INTL("Bad level: {1} (must be from 1-{2})\r\n{3}",poke[TPLEVEL],
        PBExperience::MAXLEVEL,FileLineData.linereport) if poke[TPLEVEL]<=0 || poke[TPLEVEL]>PBExperience::MAXLEVEL
      # Held item
      if !poke[TPITEM] || poke[TPITEM]==""
        poke[TPITEM]=TPDEFAULTS[TPITEM]
      else
        poke[TPITEM]=parseItem(poke[TPITEM])
      end
      # Moves
      moves=[]
      for j in [TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4]
        moves.push(parseMove(poke[j])) if poke[j] && poke[j]!=""
      end
      for j in 0...4
        index=[TPMOVE1,TPMOVE2,TPMOVE3,TPMOVE4][j]
        if moves[j] && moves[j]!=0
          poke[index]=moves[j]
        else
          poke[index]=TPDEFAULTS[index]
        end
      end
      # Ability
      if !poke[TPABILITY] || poke[TPABILITY]==""
        poke[TPABILITY]=TPDEFAULTS[TPABILITY]
      else
        poke[TPABILITY]=poke[TPABILITY].to_i
        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
      end
      # Gender
      if !poke[TPGENDER] || poke[TPGENDER]==""
        poke[TPGENDER]=TPDEFAULTS[TPGENDER]
      else
        if poke[TPGENDER]=="M"
          poke[TPGENDER]=0
        elsif poke[TPGENDER]=="F"
          poke[TPGENDER]=1
        else
          poke[TPGENDER]=poke[TPGENDER].to_i
          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
        end
      end
      # Form
      if !poke[TPFORM] || poke[TPFORM]==""
        poke[TPFORM]=TPDEFAULTS[TPFORM]
      else
        poke[TPFORM]=poke[TPFORM].to_i
        raise _INTL("Bad form: {1} (must be 0 or greater)\r\n{2}",poke[TPFORM],FileLineData.linereport) if poke[TPFORM]<0
      end
      # Shiny
      if !poke[TPSHINY] || poke[TPSHINY]==""
        poke[TPSHINY]=TPDEFAULTS[TPSHINY]
      elsif poke[TPSHINY]=="shiny"
        poke[TPSHINY]=true
      else
        poke[TPSHINY]=csvBoolean!(poke[TPSHINY].clone)
      end
      # Nature
      if !poke[TPNATURE] || poke[TPNATURE]==""
        poke[TPNATURE]=TPDEFAULTS[TPNATURE]
      else
        poke[TPNATURE]=parseNature(poke[TPNATURE])
      end
      # IVs
      if !poke[TPIV] || poke[TPIV]==""
        poke[TPIV]=TPDEFAULTS[TPIV]
      else
        poke[TPIV]=poke[TPIV].to_i
        raise _INTL("Bad IV: {1} (must be from 0-31)\r\n{2}",poke[TPIV],FileLineData.linereport) if poke[TPIV]<0 || poke[TPIV]>31
      end
      # Happiness
      if !poke[TPHAPPINESS] || poke[TPHAPPINESS]==""
        poke[TPHAPPINESS]=TPDEFAULTS[TPHAPPINESS]
      else
        poke[TPHAPPINESS]=poke[TPHAPPINESS].to_i
        raise _INTL("Bad happiness: {1} (must be from 0-255)\r\n{2}",poke[TPHAPPINESS],FileLineData.linereport) if poke[TPHAPPINESS]<0 || poke[TPHAPPINESS]>255
      end
      # Nickname
      if !poke[TPNAME] || poke[TPNAME]==""
        poke[TPNAME]=TPDEFAULTS[TPNAME]
      else
        poke[TPNAME]=poke[TPNAME].to_s
        raise _INTL("Bad nickname: {1} (must be 1-20 characters)\r\n{2}",poke[TPNAME],FileLineData.linereport) if (poke[TPNAME].to_s).length>20
      end
      # Shadow
      if !poke[TPSHADOW] || poke[TPSHADOW]==""
        poke[TPSHADOW]=TPDEFAULTS[TPSHADOW]
      else
        poke[TPSHADOW]=csvBoolean!(poke[TPSHADOW].clone)
      end
      # Ball
      if !poke[TPBALL] || poke[TPBALL]==""
        poke[TPBALL]=TPDEFAULTS[TPBALL]
      else
        poke[TPBALL]=poke[TPBALL].to_i
        raise _INTL("Bad form: {1} (must be 0 or greater)\r\n{2}",poke[TPBALL],FileLineData.linereport) if poke[TPBALL]<0
      end
      pkmn.push(poke)
    end
    i+=3+numpoke
    MessageTypes.setMessagesAsHash(MessageTypes::TrainerNames,trainernames)
    trainers.push([trainername,name,realitems,pkmn,partyid])
    nameoffset+=name.length
  end
  save_data(trainers,"Data/trainers.dat")
end

#===============================================================================
# Compile phone messages
#===============================================================================
def pbCompilePhoneData
  return if !safeExists?("PBS/phone.txt")
  database=PhoneDatabase.new
  sections=[]
  File.open("PBS/phone.txt","rb"){|f|
     pbEachSection(f){|section,name|
        if name=="<Generics>"
          database.generics=section
          sections.concat(section)
        elsif name=="<BattleRequests>"
          database.battleRequests=section 
          sections.concat(section)
        elsif name=="<GreetingsMorning>"
          database.greetingsMorning=section 
          sections.concat(section)
        elsif name=="<GreetingsEvening>"
          database.greetingsEvening=section 
          sections.concat(section)
        elsif name=="<Greetings>"
          database.greetings=section
          sections.concat(section)
        elsif name=="<Bodies1>"
          database.bodies1=section 
          sections.concat(section)
        elsif name=="<Bodies2>"
          database.bodies2=section 
          sections.concat(section)
        end
     }
  }
  MessageTypes.setMessagesAsHash(MessageTypes::PhoneMessages,sections)
  save_data(database,"Data/phone.dat")
end

#===============================================================================
# Compile metadata
#===============================================================================
class PBTrainers; end



def pbCompileMetadata
  sections=[]
  currentmap=-1
  pbCompilerEachCommentedLine("PBS/metadata.txt") {|line,lineno|
     if line[/^\s*\[\s*(\d+)\s*\]\s*$/]
       sectionname=$~[1]
       if currentmap==0
         if sections[currentmap][MetadataHome]==nil
           raise _INTL("The entry Home is required in metadata.txt section [{1}]",sectionname)
         end
         if sections[currentmap][MetadataPlayerA]==nil
           raise _INTL("The entry PlayerA is required in metadata.txt section [{1}]",sectionname)
         end
       end
       currentmap=sectionname.to_i
       sections[currentmap]=[]
     else
       if currentmap<0
         raise _INTL("Expected a section at the beginning of the file\r\n{1}",FileLineData.linereport)
       end
       if !line[/^\s*(\w+)\s*=\s*(.*)$/]
         raise _INTL("Bad line syntax (expected syntax like XXX=YYY)\r\n{1}",FileLineData.linereport)
       end
       matchData=$~
       schema=nil
       FileLineData.setSection(currentmap,matchData[1],matchData[2])
       if currentmap==0
         schema=PokemonMetadata::GlobalTypes[matchData[1]]
       else
         schema=PokemonMetadata::NonGlobalTypes[matchData[1]]
       end
       if schema
         record=pbGetCsvRecord(matchData[2],lineno,schema)
         sections[currentmap][schema[0]]=record
       end
     end
  }
  File.open("Data/metadata.dat","wb"){|f|
     Marshal.dump(sections,f)
  }
end

#===============================================================================
# Compile Battle Tower and other Cups trainers/Pokémon
#===============================================================================
def pbCompileBTTrainers(filename)
  sections=[]
  btTrainersRequiredTypes={
     "Type"=>[0,"e",PBTrainers],
     "Name"=>[1,"s"],
     "BeginSpeech"=>[2,"s"],
     "EndSpeechWin"=>[3,"s"],
     "EndSpeechLose"=>[4,"s"],
     "PokemonNos"=>[5,"*u"]
  }
  requiredtypes=btTrainersRequiredTypes
  trainernames=[]
  beginspeech=[]
  endspeechwin=[]
  endspeechlose=[]
  if safeExists?(filename)
    File.open(filename,"rb"){|f|
       FileLineData.file=filename
       pbEachFileSectionEx(f){|section,name|
          rsection=[]
          for key in section.keys
            FileLineData.setSection(name,key,section[key])
            schema=requiredtypes[key]
            next if !schema
            record=pbGetCsvRecord(section[key],0,schema)
            rsection[schema[0]]=record  
          end
          trainernames.push(rsection[1]) 
          beginspeech.push(rsection[2])
          endspeechwin.push(rsection[3])
          endspeechlose.push(rsection[4])
          sections.push(rsection)
       }
    }
  end
  MessageTypes.addMessagesAsHash(MessageTypes::TrainerNames,trainernames)
  MessageTypes.addMessagesAsHash(MessageTypes::BeginSpeech,beginspeech)
  MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechWin,endspeechwin)
  MessageTypes.addMessagesAsHash(MessageTypes::EndSpeechLose,endspeechlose)
  return sections
end

def pbCompileTrainerLists
  btTrainersRequiredTypes={
     "Trainers"=>[0,"s"],
     "Pokemon"=>[1,"s"],
     "Challenges"=>[2,"*s"]
  }
  if !safeExists?("PBS/trainerlists.txt")
    File.open("PBS/trainerlists.txt","wb"){|f|
       f.write(0xEF.chr)
       f.write(0xBB.chr)
       f.write(0xBF.chr)
       f.write("[DefaultTrainerList]\r\nTrainers=bttrainers.txt\r\nPokemon=btpokemon.txt\r\n")
    }
  end
  database=[]
  sections=[]
  MessageTypes.setMessagesAsHash(MessageTypes::BeginSpeech,[])
  MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechWin,[])
  MessageTypes.setMessagesAsHash(MessageTypes::EndSpeechLose,[])
  File.open("PBS/trainerlists.txt","rb"){|f|
     pbEachFileSectionEx(f){|section,name|
        next if name!="DefaultTrainerList" && name!="TrainerList"
        rsection=[]
        for key in section.keys
          FileLineData.setSection(name,key,section[key])
          schema=btTrainersRequiredTypes[key]
          next if key=="Challenges" && name=="DefaultTrainerList"
          next if !schema
          record=pbGetCsvRecord(section[key],0,schema)
          rsection[schema[0]]=record  
        end
        if !rsection[0]
          raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
        end
        if !rsection[1]
          raise _INTL("No trainer data file given in section {1}\r\n{2}",name,FileLineData.linereport)
        end
        rsection[3]=rsection[0]
        rsection[4]=rsection[1]
        rsection[5]=(name=="DefaultTrainerList")
        if safeExists?("PBS/"+rsection[0])
          rsection[0]=pbCompileBTTrainers("PBS/"+rsection[0])
        else
          rsection[0]=[]
        end
        if safeExists?("PBS/"+rsection[1])
          filename="PBS/"+rsection[1]
          rsection[1]=[]
          pbCompilerEachCommentedLine(filename){|line,lineno|
             rsection[1].push(PBPokemon.fromInspected(line))
          }
        else
          rsection[1]=[]
        end
        if !rsection[2]
          rsection[2]=[]
        end
        while rsection[2].include?("")
          rsection[2].delete("")
        end
        rsection[2].compact!
        sections.push(rsection)
     }
  }
  save_data(sections,"Data/trainerlists.dat")
end

#===============================================================================
# Compile wild encounters
#===============================================================================
def pbCompileEncounters
  lines=[]
  linenos=[]
  FileLineData.file="PBS/encounters.txt"
  File.open("PBS/encounters.txt","rb"){|f|
     lineno=1
     f.each_line {|line|
        if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
          line=line[3,line.length-3]
        end
        line=prepline(line)
        if line.length!=0
          lines[lines.length]=line
          linenos[linenos.length]=lineno
        end
        lineno+=1
     }
  }
  encounters={}
  thisenc=nil
  lastenc=-1
  lastenclen=0
  needdensity=false
  lastmapid=-1
  i=0;
  while i<lines.length
    line=lines[i]
    FileLineData.setLine(line,linenos[i])
    mapid=line[/^\d+$/]
    if mapid
      lastmapid=mapid
      if thisenc && (thisenc[1][EncounterTypes::Land] ||
                     thisenc[1][EncounterTypes::LandMorning] ||
                     thisenc[1][EncounterTypes::LandDay] ||
                     thisenc[1][EncounterTypes::LandNight] ||
                     thisenc[1][EncounterTypes::BugContest]) &&
                     thisenc[1][EncounterTypes::Cave]
        raise _INTL("Can't define both Land and Cave encounters in the same area (map ID {1})",mapid)
      end
      thisenc=[EncounterTypes::EnctypeDensities.clone,[]]
      encounters[mapid.to_i]=thisenc
      needdensity=true
      i+=1
      next
    end
    enc=findIndex(EncounterTypes::Names){|val| val==line}
    if enc>=0
      needdensity=false
      enclines=EncounterTypes::EnctypeChances[enc].length
      encarray=[]
      j=i+1; k=0
      while j<lines.length && k<enclines
        line=lines[j]
        FileLineData.setLine(lines[j],linenos[j])
        splitarr=strsplit(line,/\s*,\s*/)
        if !splitarr || splitarr.length<2
          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}",
             line,lastmapid,FileLineData.linereport)
        end
        splitarr[2]=splitarr[1] if splitarr.length==2
        splitarr[1]=splitarr[1].to_i
        splitarr[2]=splitarr[2].to_i
        maxlevel=PBExperience::MAXLEVEL
        if splitarr[1]<=0 || splitarr[1]>maxlevel
          raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[1],FileLineData.linereport)
        end
        if splitarr[2]<=0 || splitarr[2]>maxlevel
          raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[2],FileLineData.linereport)
        end
        if splitarr[1]>splitarr[2]
          raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}",line,FileLineData.linereport)
        end
        splitarr[0]=parseSpecies(splitarr[0])
        linearr=splitarr
        encarray.push(linearr)
        thisenc[1][enc]=encarray
        j+=1
        k+=1
      end
      if j==lines.length && k<enclines
         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}",
            enclines,lastmapid,FileLineData.linereport)
      end
      i=j
    elsif needdensity
      needdensity=false
      nums=strsplit(line,/,/)
      if nums && nums.length>=3
        for j in 0...EncounterTypes::EnctypeChances.length
          next if !EncounterTypes::EnctypeChances[j] ||
                  EncounterTypes::EnctypeChances[j].length==0
          next if EncounterTypes::EnctypeCompileDens[j]==0
          thisenc[0][j]=nums[EncounterTypes::EnctypeCompileDens[j]-1].to_i
        end
      else
        raise _INTL("Wrong syntax for densities in encounters.txt; got \"{1}\"\r\n{2}",line,FileLineData.linereport)
      end
      i+=1
    else
      raise _INTL("Undefined encounter type {1}, expected one of the following:\r\n{2}\r\n{3}",
         line,EncounterTypes::Names.inspect,FileLineData.linereport)
    end
  end
  save_data(encounters,"Data/encounters.dat")
end

#===============================================================================
# Compile Shadow moves
#===============================================================================
def pbCompileShadowMoves
  sections=[]
  if File.exists?("PBS/shadowmoves.txt")
    pbCompilerEachCommentedLine("PBS/shadowmoves.txt"){|line,lineno|
       if line[ /^([^=]+)=(.*)$/ ]
         key=$1
         value=$2
         value=value.split(",")
         species=parseSpecies(key)
         moves=[]
         for i in 0...[4,value.length].min
           moves.push((parseMove(value[i]) rescue nil))
         end
         moves.compact!
         sections[species]=moves if moves.length>0
       end
    }
  end
  save_data(sections,"Data/shadowmoves.dat")
end

#===============================================================================
# Compile battle animations
#===============================================================================
def pbCompileAnimations
  begin
    if $RPGVX
      pbanims=load_data("Data/PkmnAnimations.rvdata")
    else
      pbanims=load_data("Data/PkmnAnimations.rxdata")
    end
  rescue
    pbanims=PBAnimations.new
  end
  move2anim=[[],[]]
=begin
  if $RPGVX
    anims=load_data("Data/Animations.rvdata")
  else
    anims=load_data("Data/Animations.rxdata")
  end
  for anim in anims
    next if !anim || anim.frames.length==1
    found=false
    for i in 0...pbanims.length
      if pbanims[i] && pbanims[i].id==anim.id
        found=true if pbanims[i].array.length>1
        break
      end
    end
    if !found
      pbanims[anim.id]=pbConvertRPGAnimation(anim)
    end
  end
=end
  for i in 0...pbanims.length
    next if !pbanims[i]
    if pbanims[i].name[/^OppMove\:\s*(.*)$/]
      if Kernel.hasConst?(PBMoves,$~[1])
        moveid=PBMoves.const_get($~[1])
        move2anim[1][moveid]=i
      end
    elsif pbanims[i].name[/^Move\:\s*(.*)$/]
      if Kernel.hasConst?(PBMoves,$~[1])
        moveid=PBMoves.const_get($~[1])
        move2anim[0][moveid]=i
      end
    end
  end
  save_data(move2anim,"Data/move2anim.dat")
  save_data(pbanims,"Data/PkmnAnimations.rxdata")
end

#===============================================================================
# Generate and modify events
#===============================================================================
def pbGenerateMoveRoute(commands)
  route=RPG::MoveRoute.new
  route.repeat=false
  route.skippable=true
  route.list.clear
  i=0; while i<commands.length
    case commands[i]
    when PBMoveRoute::Wait, PBMoveRoute::SwitchOn, PBMoveRoute::SwitchOff,
         PBMoveRoute::ChangeSpeed, PBMoveRoute::ChangeFreq, PBMoveRoute::Opacity,
         PBMoveRoute::Blending, PBMoveRoute::PlaySE, PBMoveRoute::Script
      route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1]]))
      i+=1
    when PBMoveRoute::ScriptAsync
      route.list.push(RPG::MoveCommand.new(PBMoveRoute::Script,[commands[i+1]]))
      route.list.push(RPG::MoveCommand.new(PBMoveRoute::Wait,[0]))
      i+=1
    when PBMoveRoute::Jump
      route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2]]))
      i+=2
    when PBMoveRoute::Graphic
      route.list.push(RPG::MoveCommand.new(commands[i],[commands[i+1],commands[i+2],commands[i+3],commands[i+4]]))
      i+=4
    else
      route.list.push(RPG::MoveCommand.new(commands[i]))
    end
    i+=1
  end
  route.list.push(RPG::MoveCommand.new(0))
  return route
end

def pbPushMoveRoute(list,character,route,indent=0)
  if route.is_a?(Array)
    route=pbGenerateMoveRoute(route)
  end
  for i in 0...route.list.length
    list.push(RPG::EventCommand.new(
       i==0 ? 209 : 509,indent,
       i==0 ? [character,route] : [route.list[i-1]]))
  end
end

def pbPushMoveRouteAndWait(list,character,route,indent=0)
  pbPushMoveRoute(list,character,route,indent)
  pbPushEvent(list,210,[],indent)
end

def pbPushWait(list,frames,indent=0)
  pbPushEvent(list,106,[frames],indent)
end

def pbPushEvent(list,cmd,params=nil,indent=0)
  list.push(RPG::EventCommand.new(cmd,indent,params ? params : []))
end

def pbPushEnd(list)
  list.push(RPG::EventCommand.new(0,0,[]))
end

def pbPushComment(list,cmt,indent=0)
  textsplit2=cmt.split(/\n/)
  for i in 0...textsplit2.length
    list.push(RPG::EventCommand.new(i==0 ? 108 : 408,indent,[textsplit2[i].gsub(/\s+$/,"")]))
  end
end

def pbPushText(list,text,indent=0)
  return if !text
  textsplit=text.split(/\\m/)
  for t in textsplit
    first=true
    if $RPGVX
      list.push(RPG::EventCommand.new(101,indent,["",0,0,2]))
      first=false
    end
    textsplit2=t.split(/\n/)
    for i in 0...textsplit2.length
      textchunk=textsplit2[i].gsub(/\s+$/,"")
      if textchunk && textchunk!=""
        list.push(RPG::EventCommand.new(first ? 101 : 401,indent,[textchunk]))
        first=false
      end
    end
  end
end

def pbPushScript(list,script,indent=0)
  return if !script
  first=true
  textsplit2=script.split(/\n/)
  for i in 0...textsplit2.length
    textchunk=textsplit2[i].gsub(/\s+$/,"")
    if textchunk && textchunk!=""
      list.push(RPG::EventCommand.new(first ? 355 : 655,indent,[textchunk]))
      first=false
    end
  end
end

def pbPushExit(list,indent=0)
  list.push(RPG::EventCommand.new(115,indent,[]))
end

def pbPushElse(list,indent=0)
  list.push(RPG::EventCommand.new(0,indent,[]))
  list.push(RPG::EventCommand.new(411,indent-1,[]))
end

def pbPushBranchEnd(list,indent=0)
  list.push(RPG::EventCommand.new(0,indent,[]))
  list.push(RPG::EventCommand.new(412,indent-1,[]))
end

def pbPushBranch(list,script,indent=0)
  list.push(RPG::EventCommand.new(111,indent,[12,script]))
end

def pbPushSelfSwitch(list,swtch,switchOn,indent=0)
  list.push(RPG::EventCommand.new(123,indent,[swtch,switchOn ? 0 : 1]))
end

def safequote(x)
  x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  x=x.gsub(/\t/,"\\t")
  x=x.gsub(/\r/,"\\r")
  x=x.gsub(/\n/,"\\n")
  return x
end

def safequote2(x)
  x=x.gsub(/\"\#\'\\/){|a| "\\"+a }
  x=x.gsub(/\t/,"\\t")
  x=x.gsub(/\r/,"\\r")
  x=x.gsub(/\n/," ")
  return x
end

def pbEventId(event)
  list=event.pages[0].list
  return nil if list.length==0
  codes=[]
  i=0;while i<list.length
    codes.push(list[i].code)
    i+=1
  end
end



class MapData
  def initialize
    @mapinfos=pbLoadRxData("Data/MapInfos")
    @system=pbLoadRxData("Data/System")
    @tilesets=pbLoadRxData("Data/Tilesets")
    @mapxy=[]
    @mapWidths=[]
    @mapHeights=[]
    @maps=[]
    @registeredSwitches={}
  end

  def registerSwitch(switch)
    if @registeredSwitches[switch]
      return @registeredSwitches[switch]
    end
    for id in 1..5000
      [email protected][id]
      if !name || name=="" || name==switch
        @system.switches[id]=switch
        @registeredSwitches[switch]=id
        return id
      end
    end
    return 1
  end

  def saveTilesets
    filename="Data/Tilesets"
    if $RPGVX
      filename+=".rvdata"
    else
      filename+=".rxdata"
    end
    save_data(@tilesets,filename)
    filename="Data/System"
    if $RPGVX
      filename+=".rvdata"
    else
      filename+=".rxdata"
    end
    save_data(@system,filename)
  end

  def switchName(id)
    return @system.switches[id] || ""
  end

  def mapFilename(mapID)
    filename=sprintf("Data/map%03d",mapID)
    if $RPGVX
      filename+=".rvdata"
    else
      filename+=".rxdata"
    end
    return filename
  end

  def getMap(mapID)
    if @maps[mapID]
      return @maps[mapID]
    else
      begin
        @maps[mapID]=load_data(mapFilename(mapID))
        return @maps[mapID]
      rescue
        return nil
      end
    end
  end

  def isPassable?(mapID,x,y)
    if !$RPGVX
      map=getMap(mapID)
      return false if !map
      return false if x<0 || x>=map.width || y<0 || y>=map.height
      passages=@tilesets[map.tileset_id].passages
      priorities=@tilesets[map.tileset_id].priorities
      for i in [2, 1, 0]
        tile_id = map.data[x, y, i]
        return false if tile_id == nil
        return false if passages[tile_id] & 0x0f == 0x0f
        return true if priorities[tile_id] == 0
      end
    end
    return true
  end

  def setCounterTile(mapID,x,y)
    if !$RPGVX
      map=getMap(mapID)
      return if !map
      passages=@tilesets[map.tileset_id].passages
      for i in [2, 1, 0]
        tile_id = map.data[x, y, i]
        next if tile_id == 0 || tile_id==nil || !passages[tile_id]
        passages[tile_id]|=0x80
        break
      end
    end
  end

  def isCounterTile?(mapID,x,y)
    return false if $RPGVX
    map=getMap(mapID)
    return false if !map
    passages=@tilesets[map.tileset_id].passages
    for i in [2, 1, 0]
      tile_id = map.data[x, y, i]
      return false if tile_id == nil
      return true if passages[tile_id] && passages[tile_id] & 0x80 == 0x80
    end
    return false
  end

  def saveMap(mapID)
    save_data(getMap(mapID),mapFilename(mapID)) rescue nil
  end

  def getEventFromXY(mapID,x,y)
    return nil if x<0 || y<0
    mapPositions=@mapxy[mapID]
    if mapPositions
      return mapPositions[y*@mapWidths[mapID]+x]
    else
      map=getMap(mapID)
      return nil if !map
      @mapWidths[mapID]=map.width
      @mapHeights[mapID]=map.height
      mapPositions=[]
      width=map.width
      for e in map.events.values
        mapPositions[e.y*width+e.x]=e if e
      end
      @mapxy[mapID]=mapPositions
      return mapPositions[y*width+x]
    end
  end

  def getEventFromID(mapID,id)
    map=getMap(mapID)
    return nil if !map
    return map.events[id]
  end

  def mapinfos
    return @mapinfos
  end
end



class TrainerChecker
  def initialize
    @trainers=nil
    @trainertypes=nil
    @dontaskagain=false
  end

  def pbTrainerTypeCheck(symbol)
    ret=true
    if $DEBUG  
      return if @dontaskagain
      if !hasConst?(PBTrainers,symbol)
        ret=false
      else
        trtype=PBTrainers.const_get(symbol)
        @trainertypes=load_data("Data/trainertypes.dat") if !@trainertypes
        if !@trainertypes || !@trainertypes[trtype]     
          ret=false   
        end
      end  
      if !ret
        if Kernel.pbConfirmMessage(_INTL("Add new trainer named {1}?",symbol))
          pbTrainerTypeEditorNew(symbol.to_s)
          @trainers=nil
          @trainertypes=nil
        end
#        if pbMapInterpreter
#          pbMapInterpreter.command_end rescue nil
#        end
      end
    end 
    return ret
  end

  def pbTrainerBattleCheck(trtype,trname,trid)
    if $DEBUG
      return if @dontaskagain
      if trtype.is_a?(String) || trtype.is_a?(Symbol)
        pbTrainerTypeCheck(trtype)
        return if !hasConst?(PBTrainers,trtype)
        trtype=PBTrainers.const_get(trtype)
      end
      @trainers=load_data("Data/trainers.dat") if !@trainers
      if @trainers
        for trainer in @trainers
          name=trainer[1]
          thistrainerid=trainer[0]
          thispartyid=trainer[4]
          next if name!=trname || thistrainerid!=trtype || thispartyid!=trid
          return
        end
      end
      cmd=pbMissingTrainer(trtype,trname,trid)
      if cmd==2
        @dontaskagain=true
        Graphics.update
      end
      @trainers=nil
      @trainertypes=nil
    end
  end
end



def pbCompileTrainerEvents(mustcompile)
  mapdata=MapData.new
  t = Time.now.to_i
  Graphics.update
  trainerChecker=TrainerChecker.new
  for id in mapdata.mapinfos.keys.sort
    changed=false
    map=mapdata.getMap(id)
    next if !map || !mapdata.mapinfos[id]
    Win32API.SetWindowText(_INTL("Processing map {1} ({2})",id,mapdata.mapinfos[id].name))
    for key in map.events.keys
      if Time.now.to_i - t >= 5
        Graphics.update
        t = Time.now.to_i
      end
      newevent=pbConvertToTrainerEvent(map.events[key],trainerChecker)
      if newevent
        changed=true
        map.events[key]=newevent
      end
      newevent=pbConvertToItemEvent(map.events[key])
      if newevent
        changed=true
        map.events[key]=newevent
      end
      newevent=pbFixEventUse(map.events[key],id,mapdata)
      if newevent
        changed=true
        map.events[key]=newevent
      end
    end
    if Time.now.to_i - t >= 5
      Graphics.update
      t = Time.now.to_i
    end
    changed=true if pbCheckCounters(map,id,mapdata)
    if changed
      mapdata.saveMap(id)
      mapdata.saveTilesets
    end
  end
  changed=false
  if Time.now.to_i-t>=5
    Graphics.update
    t=Time.now.to_i
  end
  commonEvents=pbLoadRxData("Data/CommonEvents")
  Win32API.SetWindowText(_INTL("Processing common events"))
  for key in 0...commonEvents.length
    newevent=pbFixEventUse(commonEvents[key],0,mapdata)
    if newevent
      changed=true
      map.events[key]=newevent
    end
  end
  if changed
    if $RPGVX
      save_data(commonEvents,"Data/CommonEvents.rvdata")
    else
      save_data(commonEvents,"Data/CommonEvents.rxdata")
    end
  end
#  if !$RPGVX && $INTERNAL
#    convertVXProject(mapdata)
#  end
end

def isPlainEvent?(event)
  return event && event.pages.length<=1 && 
         event.pages[0].list.length<=1 &&
         event.pages[0].move_type==0 &&
         event.pages[0].condition.switch1_valid==false &&
         event.pages[0].condition.switch2_valid==false &&
         event.pages[0].condition.variable_valid==false &&
         event.pages[0].condition.self_switch_valid==false
end

def isPlainEventOrMart?(event)
  return event &&
         event.pages.length<=1 && 
         event.pages[0].move_type==0 &&
         event.pages[0].condition.switch1_valid==false &&
         event.pages[0].condition.switch2_valid==false &&
         event.pages[0].condition.variable_valid==false &&
         event.pages[0].condition.self_switch_valid==false &&
         ((event.pages[0].list.length<=1) || (
         event.pages[0].list.length<=12 &&
         event.pages[0].graphic.character_name!="" &&
         event.pages[0].list[0].code==355 &&
         event.pages[0].list[0].parameters[0][/^pbPokemonMart/]) || (
         event.pages[0].list.length>8 &&
         event.pages[0].graphic.character_name!="" &&
         event.pages[0].list[0].code==355 &&
         event.pages[0].list[0].parameters[0][/^Kernel\.pbSetPokemonCenter/])
         )
end

def applyPages(page,pages)
  for p in pages
    p.graphic=page.graphic
    p.walk_anime=page.walk_anime
    p.step_anime=page.step_anime
    p.direction_fix=page.direction_fix
    p.through=page.through
    p.always_on_top=page.always_on_top
  end
end

def isLikelyCounter?(thisEvent,otherEvent,mapID,mapdata)
  # Check whether other event is likely on a counter tile
  yonderX=otherEvent.x+(otherEvent.x-thisEvent.x)
  yonderY=otherEvent.y+(otherEvent.y-thisEvent.y)
  return true if mapdata.isCounterTile?(mapID,otherEvent.x,otherEvent.y)
  return thisEvent.pages[0].graphic.character_name!="" &&
         otherEvent.pages[0].graphic.character_name=="" &&
         otherEvent.pages[0].trigger==0 &&
         mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
         !mapdata.isPassable?(mapID,otherEvent.x,otherEvent.y) &&
         mapdata.isPassable?(mapID,yonderX,yonderY)
end

def isLikelyPassage?(thisEvent,mapID,mapdata)
  return false if !thisEvent || thisEvent.pages.length==0
  return false if thisEvent.pages.length!=1
  if thisEvent.pages[0].graphic.character_name=="" &&
     thisEvent.pages[0].list.length<=12 &&
     thisEvent.pages[0].list.any? {|cmd| cmd.code==201 } &&
#     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y+1) &&
     mapdata.isPassable?(mapID,thisEvent.x,thisEvent.y) &&
     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y) &&
     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y) &&
     !mapdata.isPassable?(mapID,thisEvent.x-1,thisEvent.y-1) &&
     !mapdata.isPassable?(mapID,thisEvent.x+1,thisEvent.y-1)
    return true
  end
  return false
end

def pbCheckCounters(map,mapID,mapdata)
  todelete=[]
  changed=false
  for key in map.events.keys
    event=map.events[key]
    next if !event
    firstCommand=event.pages[0].list[0]
    if isPlainEventOrMart?(event)
      # Empty event, check for counter events
      neighbors=[]
      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y-1))
      neighbors.push(mapdata.getEventFromXY(mapID,event.x,event.y+1))
      neighbors.push(mapdata.getEventFromXY(mapID,event.x-1,event.y))
      neighbors.push(mapdata.getEventFromXY(mapID,event.x+1,event.y))
      neighbors.compact!
      for otherEvent in neighbors
        next if isPlainEvent?(otherEvent)
        if isLikelyCounter?(event,otherEvent,mapID,mapdata)
          mapdata.setCounterTile(mapID,otherEvent.x,otherEvent.y)
          savedPage=event.pages[0]
          event.pages=otherEvent.pages
          applyPages(savedPage,event.pages)
          todelete.push(otherEvent.id)
          changed=true
        end
      end
    end
  end
  for key in todelete
    map.events.delete(key)
  end
  return changed
end

def pbAddPassageList(event,mapdata)
  return if !event || event.pages.length==0
  page=RPG::Event::Page.new
  page.condition.switch1_valid=true
  page.condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
  page.graphic.character_name=""
  page.trigger=3 # Autorun
  page.list.clear
  list=page.list
  pbPushBranch(list,"get_character(0).onEvent?")
  pbPushEvent(list,208,[0],1)
  pbPushWait(list,6,1)
  pbPushEvent(list,208,[1],1)
  pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
  pbPushBranchEnd(list,1)
  pbPushScript(list,"setTempSwitchOn(\"A\")")
  pbPushEnd(list)
  event.pages.push(page)
end

def pbUpdateDoor(event,mapdata)
  changed=false
  return false if event.is_a?(RPG::CommonEvent)
  if event.pages.length>=2 && 
     event.pages[event.pages.length-1].condition.switch1_valid &&
     event.pages[event.pages.length-1].condition.switch1_id==22 &&
     event.pages[event.pages.length-1].list.length>5 &&
     event.pages[event.pages.length-1].graphic.character_name!="" &&
     mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
     event.pages[event.pages.length-1].list[0].code==111
    event.pages[event.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
    changed=true
  end
  if event.pages.length>=2 && 
     event.pages[event.pages.length-1].condition.switch1_valid &&
     event.pages[event.pages.length-1].list.length>5 &&
     event.pages[event.pages.length-1].graphic.character_name!="" &&
     mapdata.switchName(event.pages[event.pages.length-1].condition.switch1_id)=='s:tsOff?("A")' &&
     event.pages[event.pages.length-1].list[0].code==111
    list=event.pages[event.pages.length-2].list
    transferCommand=list.find_all {|cmd| cmd.code==201 }
    if transferCommand.length==1 && !list.any?{|cmd| cmd.code==208 }
      list.clear
      pbPushMoveRouteAndWait(list,0,[
         PBMoveRoute::PlaySE,RPG::AudioFile.new("Entering Door"),PBMoveRoute::Wait,2,
         PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnUp,PBMoveRoute::Wait,2])
      pbPushMoveRouteAndWait(list,-1,[
         PBMoveRoute::ThroughOn,PBMoveRoute::Up,PBMoveRoute::ThroughOff])
      pbPushEvent(list,208,[0]) # Change Transparent Flag
      pbPushMoveRouteAndWait(list,0,[PBMoveRoute::Wait,2,
         PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnLeft,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnDown,PBMoveRoute::Wait,2])
      pbPushEvent(list,223,[Tone.new(-255,-255,-255),6])
      pbPushWait(list,8)
      pbPushEvent(list,208,[1])
      pbPushEvent(list,transferCommand[0].code,transferCommand[0].parameters)
      pbPushEvent(list,223,[Tone.new(0,0,0),6])
      pbPushEnd(list)
      list=event.pages[event.pages.length-1].list
      list.clear
      pbPushBranch(list,"get_character(0).onEvent?")
      pbPushEvent(list,208,[0],1)
      pbPushMoveRouteAndWait(list,0,[
         PBMoveRoute::TurnLeft,PBMoveRoute::Wait,6],1)
      pbPushEvent(list,208,[1],1)
      pbPushMoveRouteAndWait(list,-1,[PBMoveRoute::Down],1)
      pbPushMoveRouteAndWait(list,0,[
         PBMoveRoute::TurnUp,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnRight,PBMoveRoute::Wait,2,
         PBMoveRoute::TurnDown,PBMoveRoute::Wait,2],1)
      pbPushBranchEnd(list,1)
      pbPushScript(list,"setTempSwitchOn(\"A\")")
      pbPushEnd(list)
      changed=true
    end
  end
  return changed
end

def pbEventIsEmpty?(e)
  return true if !e
  return false if e.is_a?(RPG::CommonEvent)
  return e.pages.length==0
end

def pbStartsWith(s,pfx)
  return s[0,pfx.length]==pfx
end

def pbEachPage(e)
  return true if !e
  if e.is_a?(RPG::CommonEvent)
    yield e
  else
    e.pages.each {|page| yield page }
  end 
end

def pbChangeScript(script,re)
  tmp=script[0].gsub(re){ yield($~) }
  if script[0]!=tmp
    script[0]=tmp; return true
  end
  return false
end

def pbChangeScripts(script)
  changed=false
  changed|=pbChangeScript(script,/\$game_variables\[(\d+)\](?!\s*(?:\=|\!|<|>))/){|m| "pbGet("+m[1]+")" }
  changed|=pbChangeScript(script,/\$Trainer\.party\[\s*pbGet\((\d+)\)\s*\]/){|m| "pbGetPokemon("+m[1]+")" }
  return changed
end

def pbFixEventUse(event,mapID,mapdata)
  return nil if pbEventIsEmpty?(event)
  changed=false
  trainerMoneyRE=/^\s*\$Trainer\.money\s*(<|<=|>|>=)\s*(\d+)\s*$/
  itemBallRE=/^\s*(Kernel\.)?pbItemBall/
  if pbUpdateDoor(event,mapdata)
    changed=true
  end
  pbEachPage(event) do |page|
    i=0
    list=page.list
    while i<list.length
      params=list[i].parameters
      if list[i].code==655
        x=[params[0]]
        changed|=pbChangeScripts(x)
        params[0]=x[0]
      elsif list[i].code==355
        lastScript=i
        if !params[0].is_a?(String)
          i+=1
          next
        end
        x=[params[0]]
        changed|=pbChangeScripts(x)
        params[0]=x[0]
        if params[0][0,1]!="f" && params[0][0,1]!="p" && params[0][0,1]!="K"
          i+=1
          next
        end
        script=" "+params[0]
        j=i+1
        while j<list.length
          break if list[j].code!=655
          script+=list[j].parameters[0]
          lastScript=j
          j+=1
        end
        script.gsub!(/\s+/,"")
        # Using old method of recovering
        if script=="foriin$Trainer.partyi.healend"
          for j in i..lastScript
            list.delete_at(i)
          end
          list.insert(i,
             RPG::EventCommand.new(314,list[i].indent,[0]) # Recover All
          )
          changed=true
        elsif script=="pbFadeOutIn(99999){foriin$Trainer.partyi.healend}"
          oldIndent=list[i].indent
          for j in i..lastScript
            list.delete_at(i)
          end
          list.insert(i,
             RPG::EventCommand.new(223,oldIndent,[Tone.new(-255,-255,-255),6]), # Fade to black
             RPG::EventCommand.new(106,oldIndent,[6]), # Wait
             RPG::EventCommand.new(314,oldIndent,[0]), # Recover All
             RPG::EventCommand.new(223,oldIndent,[Tone.new(0,0,0),6]), # Fade to normal
             RPG::EventCommand.new(106,oldIndent,[6]) # Wait
          )
          changed=true
        end
      elsif list[i].code==108
        if params[0][/SellItem\s*\(\s*(\w+)\s*\,\s*(\d+)\s*\)/]
          itemname=$1
          cost=$2.to_i
          if hasConst?(PBItems,itemname)
            oldIndent=list[i].indent
            list.delete_at(i)
            newEvents=[]
            if cost==0
              pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent)
              pbPushText(newEvents,_INTL("Here you go!"),oldIndent+1)
              pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+1)
              pbPushElse(newEvents,oldIndent+1)
              pbPushText(newEvents,_INTL("You have no room left in the Bag."),oldIndent+1)
              pbPushBranchEnd(newEvents,oldIndent+1)
            else
              pbPushEvent(newEvents,111,[7,cost,0],oldIndent)
              pbPushBranch(newEvents,"$PokemonBag.pbCanStore?(PBItems:"+":#{itemname})",oldIndent+1)
              pbPushEvent(newEvents,125,[1,0,cost],oldIndent+2)
              pbPushText(newEvents,_INTL("\\GHere you go!"),oldIndent+2)
              pbPushScript(newEvents,"Kernel.pbReceiveItem(PBItems:"+":#{itemname})",oldIndent+2)
              pbPushElse(newEvents,oldIndent+2)
              pbPushText(newEvents,_INTL("\\GYou have no room left in the Bag."),oldIndent+2)
              pbPushBranchEnd(newEvents,oldIndent+2)
              pbPushElse(newEvents,oldIndent+1)
              pbPushText(newEvents,_INTL("\\GYou don't have enough money."),oldIndent+1)
              pbPushBranchEnd(newEvents,oldIndent+1)
            end
            list[i,0]=newEvents # insert 'newEvents' at index 'i'
            changed=true
          end
        end
      elsif list[i].code==115 && i==list.length-2
        # Superfluous exit command
        list.delete_at(i)
        changed=true
      elsif list[i].code==201 && list.length<=8
        if params[0]==0
          # Transfer back to door
          e=mapdata.getEventFromXY(params[1],params[2],params[3]-1)
          if e && e.pages.length>=2 && 
             e.pages[e.pages.length-1].condition.switch1_valid &&
             e.pages[e.pages.length-1].condition.switch1_id==22 &&
             mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)!='s:tsOff?("A")' &&
             e.pages[e.pages.length-1].list.length>5 &&
             e.pages[e.pages.length-1].list[0].code==111
            e.pages[e.pages.length-1].condition.switch1_id=mapdata.registerSwitch('s:tsOff?("A")')
            mapdata.saveMap(params[1])
            changed=true
          end
          if isLikelyPassage?(e,params[1],mapdata)
            pbAddPassageList(e,mapdata)
            mapdata.saveMap(params[1])
            changed=true
          end
          if e && e.pages.length>=2 && 
             e.pages[e.pages.length-1].condition.switch1_valid &&
            mapdata.switchName(e.pages[e.pages.length-1].condition.switch1_id)=='s:tsOff?("A")'
            # If this is really a door, move transfer target to it
            params[3]-=1
            params[5]=1 # No fade
            changed=true
          end
          deletedRoute=nil
          deleteMoveRouteAt=proc{|list,_i|
             arr=[]
             if list[_i] && list[_i].code==209
               arr.push(list[_i]);list.delete_at(_i)
               while _i<list.length
                 break if !list[_i] || list[_i].code!=509
                 arr.push(list[_i]);list.delete_at(_i)     
               end
             end
             next arr
          }
          insertMoveRouteAt=proc{|list,_i,route|
             _j=route.length-1
             while _j>=0
               list.insert(_i,route[_j])
               _j-=1
             end
          }
          if params[4]==0 && # Retain direction
             i+1<list.length && list[i+1].code==209 && list[i+1].parameters[0]==-1
            route=list[i+1].parameters[1]
            if route && route.list.length<=2
              # Delete superfluous move route command if necessary
              if route.list[0].code==16 # Player/Turn Down
                deleteMoveRouteAt.call(list,i+1); params[4]=2; changed=true
              elsif route.list[0].code==17 # Left
                deleteMoveRouteAt.call(list,i+1); params[4]=4; changed=true
              elsif route.list[0].code==18 # Right
                deleteMoveRouteAt.call(list,i+1); params[4]=6; changed=true
              elsif route.list[0].code==19 # Up
                deleteMoveRouteAt.call(list,i+1); params[4]=8; changed=true
              elsif (route.list[0].code==1 || route.list[0].code==2 ||
                 route.list[0].code==3 || route.list[0].code==4) && list.length==4
                params[4]=[0,2,4,6,8][route.list[0].code]
                deletedRoute=deleteMoveRouteAt.call(list,i+1); changed=true
              end
            end
          elsif params[4]==0 && i>3
            for j in 0...i
              if list[j].code==209 && list[j].parameters[0]==-1
                route=list[j].parameters[1]
                oldlistlength=list.length
                if route && route.list.length<=2
                  # Delete superfluous move route command if necessary
                  if route.list[0].code==16 # Player/Turn Down
                    deleteMoveRouteAt.call(list,j); params[4]=2; changed=true;i-=(oldlistlength-list.length)
                  elsif route.list[0].code==17 # Left
                    deleteMoveRouteAt.call(list,j); params[4]=4; changed=true;i-=(oldlistlength-list.length)
                  elsif route.list[0].code==18 # Right
                    deleteMoveRouteAt.call(list,j); params[4]=6; changed=true;i-=(oldlistlength-list.length)
                  elsif route.list[0].code==19 # Up
                    deleteMoveRouteAt.call(list,j); params[4]=8; changed=true;i-=(oldlistlength-list.length)
                  end
                end
              end
            end
          elsif params[4]==0 && # Retain direction
             i+2<list.length && 
             list[i+1].code==223 &&
             list[i+2].code==209 && 
             list[i+2].parameters[0]==-1
            route=list[i+2].parameters[1]
            if route && route.list.length<=2
              # Delete superfluous move route command if necessary
              if route.list[0].code==16 # Player/Turn Down
                deleteMoveRouteAt.call(list,i+2); params[4]=2; changed=true
              elsif route.list[0].code==17 # Left
                deleteMoveRouteAt.call(list,i+2); params[4]=4; changed=true
              elsif route.list[0].code==18 # Right
                deleteMoveRouteAt.call(list,i+2); params[4]=6; changed=true
              elsif route.list[0].code==19 # Up
                deleteMoveRouteAt.call(list,i+2); params[4]=8; changed=true
              end
            end
          end
        end
        # If this is the only event command, convert to a full event
        if list.length==2 || (list.length==3 && (list[0].code==250 || list[1].code==250))
          params[5]=1 # No fade
          fullTransfer=list[i]
          indent=list[i].indent
          (list.length-1).times { list.delete_at(0) }
          list.insert(0,
             RPG::EventCommand.new(250,indent,[RPG::AudioFile.new("Exit Door",80,100)]), # Play SE
             RPG::EventCommand.new(223,indent,[Tone.new(-255,-255,-255),6]), # Fade to black
             RPG::EventCommand.new(106,indent,[8]), # Wait
             fullTransfer, # Transfer event
             RPG::EventCommand.new(223,indent,[Tone.new(0,0,0),6]) # Fade to normal
          )
          changed=true
        end
        if deletedRoute
          insertMoveRouteAt.call(list,list.length-1,deletedRoute)
          changed=true
        end
      elsif list[i].code==101 
        if list[i].parameters[0][0,1]=="\\"
          newx=list[i].parameters[0].clone
          newx.sub!(/^\\[Bb]\s+/,"\\b")
          newx.sub!(/^\\[Rr]\s+/,"\\r")
          newx.sub!(/^\\[Pp][Gg]\s+/,"\\pg")
          newx.sub!(/^\\[Pp][Oo][Gg]\s+/,"\\pog")
          newx.sub!(/^\\[Gg]\s+/,"\\G")
          newx.sub!(/^\\[Cc][Nn]\s+/,"\\CN")
          if list[i].parameters[0]!=newx
            list[i].parameters[0]=newx
            changed=true
          end
        end
        lines=1
        j=i+1; while j<list.length
          break if list[j].code!=401
          if lines%4==0
            list[j].code=101
            changed=true
          end
          lines+=1
          j+=1
        end
        if lines>=2 && list[i].parameters[0].length>0 && list[i].parameters[0].length<=20 &&
           !list[i].parameters[0][/\\n/]
          # Very short line
          list[i].parameters[0]+="\\n"+list[i+1].parameters[0]
          list.delete_at(i+1)
          i-=1 # revisit this text command
          changed=true
        elsif lines>=3 && list[i+lines] && list[i+lines].code==101
          # Check whether a sentence is being broken midway 
          # between two Text commands
          lastLine=list[i+lines-1].parameters[0].sub(/\s+$/,"")
          if lastLine.length>0 && !lastLine[/[\\<]/] && lastLine[/[^\.,\!\?\;\-\"]$/]
            message=list[i].parameters[0]
            j=i+1; while j<list.length
              break if list[j].code!=401
              message+="\n"+list[j].parameters[0]
              j+=1
            end
            punct=[message.rindex(". "),message.rindex(".\n"),
               message.rindex("!"),message.rindex("?"),-1].compact.max
            if punct==-1
              punct=[message.rindex(", "),message.rindex(",\n"),-1].compact.max
            end
            if punct!=-1
              # Delete old message
              indent=list[i].indent
              newMessage=message[0,punct+1].split("\n")
              nextMessage=message[punct+1,message.length].sub(/^\s+/,"").split("\n")
              list[i+lines].code=401
              lines.times { list.delete_at(i) }
              j=nextMessage.length-1;while j>=0
                list.insert(i,RPG::EventCommand.new(
                j==0 ? 101 : 401,indent,[nextMessage[j]]))
                j-=1
              end
              j=newMessage.length-1;while j>=0
                list.insert(i,RPG::EventCommand.new(
                j==0 ? 101 : 401,indent,[newMessage[j]]))
                j-=1
              end
              changed=true
              i+=1
              next
            end
          end
        end
      elsif list[i].code==111 && list[i].parameters[0]==12
        x=
[list[i].parameters[1]]
        changed|=pbChangeScripts(x)
        list[i].parameters[1]=x[0]
        script=x[0]
        if script[trainerMoneyRE]
          # Checking money directly
          operator=$1
          amount=$2.to_i
          params[0]=7
          if operator=="<"
            params[2]=1
            params[1]=amount-1
          elsif operator=="<="
            params[2]=1
            params[1]=amount
          elsif operator==">"
            params[2]=0
            params[1]=amount+1
          elsif operator==">="
            params[2]=0
            params[1]=amount
          end
          changed=true
        elsif script[itemBallRE] && i>0
          # Using pbItemBall on non-item events
          list[i].parameters[1]=script.sub(/pbItemBall/,"pbReceiveItem")
          changed=true
        elsif script[/^\s*(Kernel\.)?(pbTrainerBattle|pbDoubleTrainerBattle)/]
          # Empty trainer battle conditional branches
          j=i+1
          isempty=true
          elseIndex=-1
          # Check if page is empty
          while j<page.list.length
            if list[j].indent<=list[i].indent
              if list[j].code==411 # Else
                elseIndex=j
              else
                break
              end
            end
            if list[j].code!=0 && list[j].code!=411
              isempty=false
              break
            end 
            j+=1
          end
          if isempty
            if elseIndex>=0
              list.insert(elseIndex+1,
                 RPG::EventCommand.new(115,list[i].indent+1,[]) # Exit Event Processing
              )
            else
              list.insert(i+1,
                 RPG::EventCommand.new(0,list[i].indent+1,[]), # Empty Event
                 RPG::EventCommand.new(411,list[i].indent,[]), # Else
                 RPG::EventCommand.new(115,list[i].indent+1,[]) # Exit Event Processing
              )
            end
            changed=true
          end
        end
      end
      i+=1
    end
  end
  return changed ? event : nil
end

def pbConvertToItemEvent(event)
  return nil if !event || event.pages.length==0
  ret=RPG::Event.new(event.x,event.y)
  name=event.name
  ret.name=event.name
  ret.id=event.id
  ret.pages=[]
  itemid=nil
  itemname=""
  hidden=false
  if name[/^HiddenItem\:\s*(\w+)\s*$/]
    itemname=$1
    return nil if !hasConst?(PBItems,itemname)
    itemid=PBItems.const_get(itemname)
    ret.name="HiddenItem"
    hidden=true
  elsif name[/^Item\:\s*(\w+)\s*$/]
    itemname=$1
    return nil if !hasConst?(PBItems,itemname)
    itemid=PBItems.const_get(itemname)
    ret.name="Item"
  else
    return nil
  end
  # Event page 1
  page=RPG::Event::Page.new
  if !hidden
    page.graphic.character_name="Object ball"
  end
  page.list=[]
  pbPushBranch(page.list,
     sprintf("Kernel.pbItemBall(:%s)",itemname))
  pbPushSelfSwitch(page.list,"A",true,1)
  pbPushElse(page.list,1)
  pbPushBranchEnd(page.list,1)
  pbPushEnd(page.list)
  ret.pages.push(page)
  # Event page 2
  page=RPG::Event::Page.new
  page.condition.self_switch_valid=true
  page.condition.self_switch_ch="A"
  ret.pages.push(page)
  return ret
end

def pbConvertToTrainerEvent(event,trainerChecker)
  return nil if !event || event.pages.length==0
  ret=RPG::Event.new(event.x,event.y)
  ret.name=event.name
  ret.id=event.id
  commands=[]
  list=event.pages[0].list
  return nil if list.length<2
  isFirstCommand=false
  i=0; while i<list.length
    if list[i].code==108
      command=list[i].parameters[0]
      j=i+1; while j<list.length
        break if list[j].code!=408
        command+="\r\n"+list[j].parameters[0]
        j+=1
      end
      if command[/^(Battle\:|Type\:|Name\:|EndSpeech\:|VanishIfSwitch\:|EndBattle\:|RegSpeech\:|BattleID\:|EndIfSwitch\:|DoubleBattle\:|Backdrop\:|Continue\:|Outcome\:)/i]
        commands.push(command)
        isFirstCommand=true if i==0
      end
    end
    i+=1
  end
  return nil if commands.length==0
  if isFirstCommand && !event.name[/Trainer/]
    ret.name="Trainer(3)"
  elsif isFirstCommand && event.name[/^\s*Trainer\s+\((\d+)\)\s*$/]
    ret.name="Trainer(#{$1})"
  end
  firstpage=Marshal::load(Marshal.dump(event.pages[0]))
  firstpage.trigger=2
  firstpage.list=[]
  trtype=nil
  trname=nil
  battles=[]
  endbattles=[]
  realcommands=[]
  endspeeches=[]
  regspeech=nil
  backdrop=nil
  battleid=0
  endifswitch=[]
  vanishifswitch=[]
  doublebattle=false
  continue=false
  outcome=0
  for command in commands
    if command[/^Battle\:\s*([\s\S]+)$/i]
      battles.push($~[1])
      pbPushComment(firstpage.list,command)
    end
    if command[/^Type\:\s*([\s\S]+)$/i]
      trtype=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      pbPushComment(firstpage.list,command)
    end
    if command[/^Name\:\s*([\s\S]+)$/i]
      trname=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      pbPushComment(firstpage.list,command)
    end
    if command[/^EndSpeech\:\s*([\s\S]+)$/i]
      endspeeches.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
      pbPushComment(firstpage.list,command)
    end
    if command[/^EndIfSwitch\:\s*([\s\S]+)$/i]
      endifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
      pbPushComment(firstpage.list,command)
    end
    if command[/^DoubleBattle\:\s*([\s\S]+)$/i]
      value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      doublebattle=true if value.upcase=="TRUE" || value.upcase=="YES"
      pbPushComment(firstpage.list,command)
    end
    if command[/^VanishIfSwitch\:\s*([\s\S]+)$/i]
      vanishifswitch.push(($~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")).to_i)
      pbPushComment(firstpage.list,command)
    end
    if command[/^Backdrop\:\s*([\s\S]+)$/i]
      backdrop=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      pbPushComment(firstpage.list,command)
    end
    if command[/^RegSpeech\:\s*([\s\S]+)$/i]
      regspeech=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      pbPushComment(firstpage.list,command)
    end
    if command[/^EndBattle\:\s*([\s\S]+)$/i]
      endbattles.push($~[1].gsub(/^\s+/,"").gsub(/\s+$/,""))
      pbPushComment(firstpage.list,command)
    end
    if command[/^BattleID\:\s*(\d+)$/i]
      battleid=$~[1].to_i
      pbPushComment(firstpage.list,command)
    end
    if command[/^Continue\:\s*([\s\S]+)$/i]
      value=$~[1].gsub(/^\s+/,"").gsub(/\s+$/,"")
      continue=true if value.upcase=="TRUE" || value.upcase=="YES"
      pbPushComment(firstpage.list,command)
    end
    if command[/^Outcome\:\s*(\d+)$/i]
      outcome=$~[1].to_i
      pbPushComment(firstpage.list,command)
    end
  end
  if battles.length<=0
    return nil
  end
  if firstpage.graphic.character_name=="" && hasConst?(PBTrainers,trtype)
    trainerid=getConst(PBTrainers,trtype)
    if trainerid
      filename=pbTrainerCharNameFile(trainerid)
      if FileTest.image_exist?("Graphics/Characters/"+filename)
        firstpage.graphic.character_name=sprintf(filename)
      end
    end
  end
  safetrcombo=sprintf("PBTrainers:"+":%s,\"%s\"",trtype,safequote(trname))
  safetrcombo2=sprintf(":%s,\"%s\"",trtype,safequote(trname))
  introplay=sprintf("pbTrainerIntro(:%s)",trtype)
  pbPushScript(firstpage.list,introplay)
  pbPushScript(firstpage.list,"Kernel.pbNoticePlayer(get_character(0))")
  pbPushText(firstpage.list,battles[0])
  if battles.length>1
    pbPushScript(firstpage.list,sprintf("Kernel.pbTrainerCheck(%s,%d,%d)",safetrcombo2,battles.length,battleid))
  end
  if backdrop
    pbPushScript(firstpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)))
  end
  espeech=(endspeeches[0]) ? endspeeches[0] : "..."
  # Run trainer check now, except in editor
  trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid) if !$INEDITOR
  pbPushBranch(firstpage.list,
     sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s,%d)",
     safetrcombo,safequote2(espeech),
     doublebattle ? "true" : "false",
     battleid,
     continue ? "true" : "false",
     outcome)
  )
  if battles.length>1
    pbPushScript(firstpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
  end
  pbPushSelfSwitch(firstpage.list,"A",true,1)
  pbPushBranchEnd(firstpage.list,1)
  pbPushScript(firstpage.list,"pbTrainerEnd",0)
  pbPushEnd(firstpage.list)
  secondpage=Marshal::load(Marshal.dump(firstpage))
  secondpage.list=[]
  secondpage.trigger=0
  secondpage.condition=firstpage.condition.clone
  thirdpage=Marshal::load(Marshal.dump(secondpage))
  thirdpage.list=secondpage.list.clone
  thirdpage.condition=secondpage.condition.clone
  secondpage.condition.self_switch_valid=true
  secondpage.condition.self_switch_ch="A"
  thirdpage.condition.self_switch_valid=true
  thirdpage.condition.self_switch_ch="B"
  for i in 1...battles.length
    if endspeeches.length==0
      espeech="..."
    else
      espeech=(endspeeches[i]) ? endspeeches[i] : endspeeches[endspeeches.length-1]
    end
    if endbattles.length==0
      ebattle=nil
    else
      ebattle=(endbattles[i]) ? endbattles[i] : endbattles[endbattles.length-1]
    end
    if i==battles.length-1
      pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)>=%d",safetrcombo,i))
      pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)>%d",safetrcombo,i))
    else
      pbPushBranch(thirdpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
      pbPushBranch(secondpage.list,sprintf("pbPhoneBattleCount(%s)==%d",safetrcombo,i))
    end
    pbPushText(secondpage.list,ebattle,1)
    pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length),1)
    pbPushExit(secondpage.list,1)
    pbPushBranchEnd(secondpage.list,1)
    pbPushScript(thirdpage.list,introplay,1)
    pbPushText(thirdpage.list,battles[i],1)
    # Run trainer check now, except in editor
    trainerChecker.pbTrainerBattleCheck(trtype,trname,battleid+i) if !$INEDITOR
    if backdrop
      pbPushScript(thirdpage.list,sprintf("$PokemonGlobal.nextBattleBack=\"%s\"",safequote(backdrop)),1)
    end
    pbPushBranch(thirdpage.list,
       sprintf("pbTrainerBattle(%s,_I(\"%s\"),%s,%d,%s,%d)",
       safetrcombo,safequote2(espeech),
       doublebattle ? "true" : "false",
       battleid+i,
       continue ? "true" : "false",
       outcome),1
    )
    pbPushScript(thirdpage.list,
       sprintf("pbPhoneIncrement(%s,%d)",safetrcombo,battles.length),2)
    pbPushSelfSwitch(thirdpage.list,"A",true,2)
    pbPushSelfSwitch(thirdpage.list,"B",false,2)
    pbPushScript(thirdpage.list,"pbTrainerEnd",2)
    pbPushBranchEnd(thirdpage.list,2)
    pbPushExit(thirdpage.list,1)
    pbPushBranchEnd(thirdpage.list,1)
  end
  ebattle=(endbattles[0]) ? endbattles[0] : "..."
  pbPushText(secondpage.list,ebattle)
  if battles.length>1
    pbPushScript(secondpage.list,sprintf("pbPhoneRegisterBattle(_I(\"%s\"),get_character(0),%s,%d)",regspeech,safetrcombo,battles.length))
  end
  pbPushEnd(secondpage.list)
  pbPushEnd(thirdpage.list)
  if battles.length==1
    ret.pages=[firstpage,secondpage]
  else
    ret.pages=[firstpage,thirdpage,secondpage]
  end
  for endswitch in endifswitch
    ebattle=(endbattles[0]) ? endbattles[0] : "..."
    endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
    endIfSwitchPage.condition=secondpage.condition.clone
    if endIfSwitchPage.condition.switch1_valid
      endIfSwitchPage.condition.switch2_valid=true
      endIfSwitchPage.condition.switch2_id=endswitch
    else
      endIfSwitchPage.condition.switch1_valid=true
      endIfSwitchPage.condition.switch1_id=endswitch
    end
    endIfSwitchPage.condition.self_switch_valid=false
    endIfSwitchPage.list=[]
    pbPushText(endIfSwitchPage.list,ebattle)
    pbPushEnd(endIfSwitchPage.list)
    ret.pages.push(endIfSwitchPage)
  end
  for endswitch in vanishifswitch
    ebattle=(endbattles[0]) ? endbattles[0] : "..."
    endIfSwitchPage=Marshal::load(Marshal.dump(secondpage))
    endIfSwitchPage.graphic.character_name="" # make blank
    endIfSwitchPage.condition=secondpage.condition.clone
    if endIfSwitchPage.condition.switch1_valid
      endIfSwitchPage.condition.switch2_valid=true
      endIfSwitchPage.condition.switch2_id=endswitch
    else
      endIfSwitchPage.condition.switch1_valid=true
      endIfSwitchPage.condition.switch1_id=endswitch
    end
    endIfSwitchPage.condition.self_switch_valid=false
    endIfSwitchPage.list=[]
    pbPushEnd(endIfSwitchPage.list)
    ret.pages.push(endIfSwitchPage)
  end
  return ret
end

#===============================================================================
# Add new map files to the map tree
#===============================================================================
def pbImportNewMaps
  return false if !$DEBUG
  mapfiles={}
  # Get IDs of all maps in the Data folder
  Dir.chdir("Data"){
     mapdata=sprintf("Map*.%s","rxdata",$RPGVX ? "rvdata" : "rxdata")
     for map in Dir.glob(mapdata)
       if map[/map(\d+)\.rxdata/i]
         mapfiles[$1.to_i(10)]=true
       end
     end
  }
  mapinfos=pbLoadRxData("Data/MapInfos")
  maxOrder=0
  # Exclude maps found in mapinfos
  for id in mapinfos.keys
    next if !mapinfos.id
    if mapfiles[id]
      mapfiles.delete(id)
    end
    maxOrder=[maxOrder,mapinfos[id].order].max
  end
  # Import maps not found in mapinfos
  maxOrder+=1
  imported=false
  for id in mapfiles.keys
    next if id==999 # Ignore 999 (random dungeon map)
    mapname=sprintf("MAP%03d",id)
    mapinfo=RPG::MapInfo.new
    mapinfo.order=maxOrder
    maxOrder+=1
    mapinfo.name=mapname
    mapinfos[id]=mapinfo
    imported=true
  end
  if imported
    if $RPGVX
      save_data(mapinfos,"Data/MapInfos.rvdata")
    else
      save_data(mapinfos,"Data/MapInfos.rxdata") 
    end
    Kernel.pbMessage(_INTL("New maps copied to the Data folder were successfully imported.",id))
  end
  return imported
end

#===============================================================================
# Compile all data
#===============================================================================
def pbCompileAllData(mustcompile)
  FileLineData.clear
  if mustcompile
    if (!$INEDITOR || LANGUAGES.length<2) && pbRgssExists?("Data/messages.dat")
      MessageTypes.loadMessageFile("Data/messages.dat")
    end
    # No dependencies
    yield(_INTL("Compiling type data"))
    pbCompileTypes
    # No dependencies
    yield(_INTL("Compiling town map data"))
    pbCompileTownMap
    # No dependencies
    yield(_INTL("Compiling map connection data"))
    pbCompileConnections
    # No dependencies  
    yield(_INTL("Compiling ability data"))
    pbCompileAbilities
    # Depends on PBTypes
    yield(_INTL("Compiling move data"))
    pbCompileMoves
    # Depends on PBMoves
    yield(_INTL("Compiling item data"))
    pbCompileItems
    # Depends on PBItems
    yield(_INTL("Compiling berry plant data"))
    pbCompileBerryPlants
    # Depends on PBMoves, PBItems, PBTypes, PBAbilities
    yield(_INTL("Compiling Pokemon data"))
    pbCompilePokemonData
    # Depends on PBSpecies, PBMoves
    yield(_INTL("Compiling machine data"))
    pbCompileMachines
    # Depends on PBSpecies, PBItems, PBMoves
    yield(_INTL("Compiling Trainer data"))
    pbCompileTrainers
    # Depends on PBTrainers
    yield(_INTL("Compiling phone data"))
    pbCompilePhoneData
    # Depends on PBTrainers
    yield(_INTL("Compiling metadata"))
    pbCompileMetadata
    # Depends on PBTrainers
    yield(_INTL("Compiling battle Trainer data"))
    pbCompileTrainerLists
    # Depends on PBSpecies
    yield(_INTL("Compiling encounter data"))
    pbCompileEncounters
    # Depends on PBSpecies, PBMoves
    yield(_INTL("Compiling shadow move data"))
    pbCompileShadowMoves
    #Depends on PBContestMoves #~ Required for Pokémon Contests
    yield(_INTL("Compiling contest moves"))
    pbCompileContestMoves
    yield(_INTL("Compiling messages"))
  else
    if (!$INEDITOR || LANGUAGES.length<2) && safeExists?("Data/messages.dat")
      MessageTypes.loadMessageFile("Data/messages.dat")
    end
  end
  pbCompileAnimations
  pbCompileTrainerEvents(mustcompile)
  pbSetTextMessages
  MessageTypes.saveMessages
  if !$INEDITOR && LANGUAGES.length>=2
    pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
  end
end

begin
  if $DEBUG
    datafiles=[
               "attacksRS.dat",
               "berryplants.dat",
               "connections.dat",
               "dexdata.dat",
               "eggEmerald.dat",
               "encounters.dat",
               "evolutions.dat",
               "items.dat",
               "metadata.dat",
               "metrics.dat",
               "moves.dat",
               "contestmoves.dat", #~ Required for Pokémon Contests
               "phone.dat",
               "regionals.dat",
               "shadowmoves.dat",
               "tm.dat",
               "townmap.dat",
               "trainerlists.dat",
               "trainers.dat",
               "trainertypes.dat",
               "types.dat",
               "Constants.rxdata"
               ]
    textfiles=[
               "abilities.txt",
               "berryplants.txt",
               "connections.txt",
               "encounters.txt",
               "items.txt",
               "metadata.txt",
               "moves.txt",
               "contestmoves.txt", #~ Required for Pokémon Contests            
               "phone.txt",
               "pokemon.txt",
               "shadowmoves.txt",
               "tm.txt",
               "townmap.txt",
               "trainerlists.txt",
               "trainers.txt",
               "trainertypes.txt",
               "types.txt"
               ]
    latestdatatime=0
    latesttexttime=0
    mustcompile=false
    mustcompile|=pbImportNewMaps
    mustcompile|=!(PBSpecies.respond_to?("maxValue") rescue false)
    if !safeIsDirectory?("PBS")
      Dir.mkdir("PBS") rescue nil
      pbSaveAllData()
      mustcompile=true
    end
    for i in 0...datafiles.length
      begin
        File.open("Data/#{datafiles[i]}"){|file|
           latestdatatime=[latestdatatime,file.mtime.to_i].max
        }
      rescue SystemCallError
        mustcompile=true
      end
    end
    for i in 0...textfiles.length
      begin
        File.open("PBS/#{textfiles[i]}"){|file|
           latesttexttime=[latesttexttime,file.mtime.to_i].max
        }
      rescue SystemCallError
      end
    end
    mustcompile=mustcompile || (latesttexttime>=latestdatatime)
    Input.update
    mustcompile=true if Input.press?(Input::CTRL)
    if mustcompile
      for i in 0...datafiles.length
        begin
          File.delete("Data/#{datafiles[i]}")
        rescue SystemCallError
        end
      end
    end
    pbCompileAllData(mustcompile){|msg| Win32API.SetWindowText(msg) }
  end
rescue Exception
  e=$!
  raise e if "#{e.class}"=="Reset" || e.is_a?(Reset) || e.is_a?(SystemExit)
  pbPrintException(e)
  for i in 0...datafiles.length
    begin
      File.delete("Data/#{datafiles[i]}")
    rescue SystemCallError
    end
  end
  raise Reset.new if e.is_a?(Hangup)
  loop do
    Graphics.update
  end
end

And Intl_Messages should be this:
Code:
def pbAddScriptTexts(items,script)
  script.scan(/(?:_I)\s*\(\s*\"((?:[^\\\"]*\\\"?)*[^\"]*)\"/){|s|
     string=s[0]
     string.gsub!(/\\\"/,"\"")
     string.gsub!(/\\\\/,"\\")
     items.push(string)
  }
end

def pbAddRgssScriptTexts(items,script)
  script.scan(/(?:_INTL|_ISPRINTF)\s*\(\s*\"((?:[^\\\"]*\\\"?)*[^\"]*)\"/){|s|
     string=s[0]
     string.gsub!(/\\r/,"\r")
     string.gsub!(/\\n/,"\n")
     string.gsub!(/\\1/,"\1")
     string.gsub!(/\\\"/,"\"")
     string.gsub!(/\\\\/,"\\")
     items.push(string)
  }
end

def pbSetTextMessages
  Graphics.update
  begin
    t = Time.now.to_i
    texts=[]
    for script in $RGSS_SCRIPTS
      if Time.now.to_i - t >= 5
        t = Time.now.to_i
        Graphics.update
      end
      scr=Zlib::Inflate.inflate(script[2])
      pbAddRgssScriptTexts(texts,scr)
    end
    # Must add messages because this code is used by both game system and Editor
    MessageTypes.addMessagesAsHash(MessageTypes::ScriptTexts,texts)
    commonevents=pbLoadRxData("Data/CommonEvents")
    items=[]
    choices=[]
    for event in commonevents.compact
      if Time.now.to_i - t >= 5
        t = Time.now.to_i
        Graphics.update
      end
      begin
        neednewline=false
        lastitem=""
        for j in 0...event.list.size
          list = event.list[j]
          if neednewline && list.code!=401
            if lastitem!=""
              lastitem.gsub!(/([^\.\!\?])\s\s+/){|m| $1+" "}
              items.push(lastitem)
              lastitem=""
            end         
            neednewline=false
          end
          if list.code == 101
            lastitem+="#{list.parameters[0]}" if !$RPGVX
            neednewline=true
          elsif list.code == 102
            for k in 0...list.parameters[0].length
              choices.push(list.parameters[0][k])
            end
            neednewline=false
          elsif list.code == 401
            lastitem+=" " if lastitem!=""
            lastitem+="#{list.parameters[0]}"
            neednewline=true
          elsif list.code == 355 || list.code == 655
            pbAddScriptTexts(items,list.parameters[0])
          elsif list.code == 111 && list.parameters[0]==12
            pbAddScriptTexts(items,list.parameters[1])
          elsif list.code == 209
            route=list.parameters[1]
            for k in 0...route.list.size
              if route.list[k].code == 45
                pbAddScriptTexts(items,route.list[k].parameters[0])
              end
            end
          end
        end
        if neednewline
          if lastitem!=""
            items.push(lastitem)
            lastitem=""
          end         
        end
      end
    end
    if Time.now.to_i - t >= 5
      t = Time.now.to_i
      Graphics.update
    end
    items|=[]
    choices|=[]
    items.concat(choices)
    MessageTypes.setMapMessagesAsHash(0,items)
    mapinfos = pbLoadRxData("Data/MapInfos")
    mapnames=[]
    for id in mapinfos.keys
      mapnames[id]=mapinfos[id].name
    end
    MessageTypes.setMessages(MessageTypes::MapNames,mapnames)
    for id in mapinfos.keys
      if Time.now.to_i - t >= 5
        t = Time.now.to_i
        Graphics.update
      end
      filename=sprintf("Data/Map%03d.%s",id,$RPGVX ? "rvdata" : "rxdata")
      next if !pbRgssExists?(filename)
      map = load_data(filename)
      items=[]
      choices=[]
      for event in map.events.values
        if Time.now.to_i - t >= 5
          t = Time.now.to_i
          Graphics.update
        end
        begin
          for i in 0...event.pages.size
            neednewline=false
            lastitem=""
            for j in 0...event.pages[i].list.size
              list = event.pages[i].list[j]
              if neednewline && list.code!=401
                if lastitem!=""
                  lastitem.gsub!(/([^\.\!\?])\s\s+/){|m| $1+" "}
                  items.push(lastitem)
                  lastitem=""
                end         
                neednewline=false
              end
              if list.code == 101
                lastitem+="#{list.parameters[0]}" if !$RPGVX
                neednewline=true
              elsif list.code == 102
                for k in 0...list.parameters[0].length
                  choices.push(list.parameters[0][k])
                end
                neednewline=false
              elsif list.code == 401
                lastitem+=" " if lastitem!=""
                lastitem+="#{list.parameters[0]}"
                neednewline=true
              elsif list.code == 355 || list.code==655
                pbAddScriptTexts(items,list.parameters[0])
              elsif list.code == 111 && list.parameters[0]==12
                pbAddScriptTexts(items,list.parameters[1])
              elsif list.code==209
                route=list.parameters[1]
                for k in 0...route.list.size
                  if route.list[k].code==45
                    pbAddScriptTexts(items,route.list[k].parameters[0])
                  end
                end
              end
            end
            if neednewline
              if lastitem!=""
                items.push(lastitem)
                lastitem=""
              end         
            end
          end
        end
      end
      if Time.now.to_i - t >= 5
        t = Time.now.to_i
        Graphics.update
      end
      items|=[]
      choices|=[]
      items.concat(choices)
      MessageTypes.setMapMessagesAsHash(id,items)
      if Time.now.to_i - t >= 5
        t = Time.now.to_i
        Graphics.update
      end
    end
  rescue Hangup
  end
  Graphics.update
end

def pbEachIntlSection(file)
  lineno=1
  re=/^\s*\[\s*([^\]]+)\s*\]\s*$/
  havesection=false
  sectionname=nil
  lastsection=[]
  file.each_line {|line|
     if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
       line=line[3,line.length-3]
     end
     if !line[/^\#/] && !line[/^\s*$/]
       if line[re]
         if havesection
           yield lastsection,sectionname 
         end
         lastsection.clear
         sectionname=$~[1]
         havesection=true
       else
         if sectionname==nil
           raise _INTL("Expected a section at the beginning of the file (line {1})",lineno)
         end
         lastsection.push(line.gsub(/\s+$/,""))
       end
     end
     lineno+=1
     if lineno%500==0
       Graphics.update
     end
  }
  if havesection
    yield lastsection,sectionname 
  end
end

def pbGetText(infile)
  begin
    file=File.open(infile,"rb") 
  rescue
    raise _INTL("Can't find {1}",infile)
  end
  intldat=[]
  begin
    pbEachIntlSection(file){|section,name|
       index=name
       if section.length==0
         next
       end
       if !name[/^([Mm][Aa][Pp])?(\d+)$/]
         raise _INTL("Invalid section name {1}",name)
       end
       ismap=$~[1] && $~[1]!=""
       id=$~[2].to_i
       itemlength=0
       if section[0][/^\d+$/]
         intlhash=[]
         itemlength=3
         if ismap
           raise _INTL("Section {1} can't be an ordered list (section was recognized as an ordered list because its first line is a number)",name)
         end
         if section.length%3!=0
           raise _INTL("Section {1}'s line count is not divisible by 3 (section was recognized as an ordered list because its first line is a number)",name)
         end
       else
         intlhash=OrderedHash.new
         itemlength=2
         if section.length%2!=0
           raise _INTL("Section {1} has an odd number of entries (section was recognized as a hash because its first line is not a number)",name)
         end
       end
       i=0;loop do break unless i<section.length
         if itemlength==3
           if !section[i][/^\d+$/]
             raise _INTL("Expected a number in section {1}, got {2} instead",name,section[i])
           end
           key=section[i].to_i
           i+=1
         else
           key=MessageTypes.denormalizeValue(section[i])
         end
         intlhash[key]=MessageTypes.denormalizeValue(section[i+1])
         i+=2
       end
       if ismap
         intldat[0]=[] if !intldat[0]
         intldat[0][id]=intlhash
       else
         intldat[id]=intlhash
       end
    }
  ensure
    file.close
  end
  return intldat
end

def pbCompileText
  outfile=File.open("intl.dat","wb")
  begin
    intldat=pbGetText("intl.txt")
    Marshal.dump(intldat,outfile)
  rescue
    raise
  ensure
    outfile.close
  end
end



class OrderedHash < Hash
  def initialize
    @keys=[]
    super
  end

  def keys
    return @keys.clone
  end

  def inspect
    str="{"
    for i in [email protected]
      str+=", " if i>0
      str+=@keys[i].inspect+"=>"+self[@keys[i]].inspect
    end
    str+="}"
    return str
  end

  alias :to_s :inspect

  def []=(key,value)
    oldvalue=self[key]
    if !oldvalue && value
      @keys.push(key)
    elsif !value
      @keys|=[]
      @keys-=[key]
    end
    return super(key,value)
  end

  def self._load(string)
    ret=self.new
    keysvalues=Marshal.load(string)
    keys=keysvalues[0]
    values=keysvalues[1]
    for i in 0...keys.length
      ret[keys[i]]=values[i]
    end
    return ret
  end

  def _dump(depth=100)
    values=[]
    for key in @keys
      values.push(self[key])
    end
    return Marshal.dump([@keys,values])
  end
end



class Messages
  def initialize(filename=nil,delayLoad=false)
    @messages=nil
    @filename=filename
    if @filename && !delayLoad
      loadMessageFile(@filename)
    end
  end

  def delayedLoad
    if @filename && !@messages
      loadMessageFile(@filename)
      @filename=nil
    end
  end

  def self.stringToKey(str)
    if str[/[\r\n\t\1]|^\s+|\s+$|\s{2,}/]
       key=str.clone
       key.gsub!(/^\s+/,"")
       key.gsub!(/\s+$/,"")
       key.gsub!(/\s{2,}/," ")
       return key
    end
    return str
  end

  def self.normalizeValue(value)
    if value[/[\r\n\t\x01]|^[\[\]]/]
      ret=value.clone
      ret.gsub!(/\r/,"<<r>>")
      ret.gsub!(/\n/,"<<n>>")
      ret.gsub!(/\t/,"<<t>>")
      ret.gsub!(/\[/,"<<[>>")
      ret.gsub!(/\]/,"<<]>>")
      ret.gsub!(/\x01/,"<<1>>")
      return ret
    end
    return value
  end

  def self.denormalizeValue(value)
    if value[/<<[rnt1\[\]]>>/]
      ret=value.clone
      ret.gsub!(/<<1>>/,"\1")
      ret.gsub!(/<<r>>/,"\r")
      ret.gsub!(/<<n>>/,"\n")
      ret.gsub!(/<<\[>>/,"[")
      ret.gsub!(/<<\]>>/,"]")
      ret.gsub!(/<<t>>/,"\t")
      return ret
    end
    return value
  end

  def self.writeObject(f,msgs,secname,origMessages=nil)
    return if !msgs
    if msgs.is_a?(Array)
      f.write("[#{secname}]\r\n")
      for j in 0...msgs.length
        next if msgs[j]==nil || msgs[j]==""
        value=Messages.normalizeValue(msgs[j])
        origValue=""
        if origMessages
          origValue=Messages.normalizeValue(origMessages.get(secname,j))
        else
          origValue=Messages.normalizeValue(MessageTypes.get(secname,j))
        end
        f.write("#{j}\r\n")
        f.write(origValue+"\r\n")
        f.write(value+"\r\n")
      end
    elsif msgs.is_a?(OrderedHash)
      f.write("[#{secname}]\r\n")
      keys=msgs.keys
      for key in keys
        next if msgs[key]==nil || msgs[key]==""
        value=Messages.normalizeValue(msgs[key])
        valkey=Messages.normalizeValue(key)
        # key is already serialized
        f.write(valkey+"\r\n")
        f.write(value+"\r\n")
      end
    end
  end

  def messages
    return @messages || []
  end

  def extract(outfile)
#    return if !@messages
    origMessages=Messages.new("Data/messages.dat")
    File.open(outfile,"wb"){|f|
       f.write(0xef.chr)
       f.write(0xbb.chr)
       f.write(0xbf.chr)
       f.write("# To localize this text for a particular language, please\r\n")
       f.write("# translate every second line of this file.\r\n")
       if origMessages.messages[0]
         for i in 0...origMessages.messages[0].length
           msgs=origMessages.messages[0][i]
           Messages.writeObject(f,msgs,"Map#{i}",origMessages)
         end
       end
       for i in 1...origMessages.messages.length
         msgs=origMessages.messages[i]
         Messages.writeObject(f,msgs,i,origMessages)
       end
    }
  end

  def setMessages(type,array)
    arr=[]
    @messages=[] if !@messages
    for i in 0...array.length
      arr[i]=(array[i]) ? array[i] : ""
    end
    @messages[type]=arr
  end

  def self.createHash(type,array)
    arr=OrderedHash.new
    for i in 0...array.length
      if array[i]
        key=Messages.stringToKey(array[i])
        arr[key]=array[i]
      end
    end
    return arr
  end

  def self.addToHash(type,array,hash)
    if !hash
      hash=OrderedHash.new
    end
    for i in 0...array.length
      if array[i]
        key=Messages.stringToKey(array[i])
        hash[key]=array[i]
      end
    end
    return hash
  end

  def setMapMessagesAsHash(type,array)
    @messages=[] if !@messages
    @messages[0]=[] if !@messages[0]
    @messages[0][type]=Messages.createHash(type,array)
  end

  def addMapMessagesAsHash(type,array)
    @messages=[] if !@messages
    @messages[0]=[] if !@messages[0]
    @messages[0][type]=Messages.addToHash(type,array,@messages[0][type])
  end

  def setMessagesAsHash(type,array)
    @messages=[] if !@messages
    @messages[type]=Messages.createHash(type,array)
  end

  def addMessagesAsHash(type,array)
    @messages=[] if !@messages
    @messages[type]=Messages.addToHash(type,array,@messages[type])
  end

  def saveMessages(filename=nil)
    filename="Data/messages.dat" if !filename
    File.open(filename,"wb"){|f|
       Marshal.dump(@messages,f)
    }
  end

  def loadMessageFile(filename)
    begin
      Kernel.pbRgssOpen(filename,"rb"){|f|
         @messages=Marshal.load(f)
      }
      if [email protected]_a?(Array)
        @messages=nil
        raise "Corrupted data"
      end
      return @messages
    rescue
      @messages=nil
      return nil
    end
  end

  def set(type,id,value)
    delayedLoad
    return if !@messages
    return if !@messages[type]
    @messages[type][id]=value
  end

  def getCount(type)
    delayedLoad
    return 0 if !@messages
    return 0 if !@messages[type]
    return @messages[type].length
  end

  def get(type,id)
    delayedLoad
    return "" if !@messages
    return "" if !@messages[type]
    return "" if !@messages[type][id]
    return @messages[type][id]
  end

  def getFromHash(type,key)
    delayedLoad
    return key if !@messages
    return key if !@messages[type]
    id=Messages.stringToKey(key)
    return key if !@messages[type][id]
    return @messages[type][id]
  end

  def getFromMapHash(type,key)
    delayedLoad
    return key if !@messages
    return key if !@messages[0]
    return key if !@messages[0][type] && !@messages[0][0]
    id=Messages.stringToKey(key)
    if @messages[0][type] &&  @messages[0][type][id]
      return @messages[0][type][id]
    elsif @messages[0][0] && @messages[0][0][id]
      return @messages[0][0][id]
    end
    return key
  end
end



module MessageTypes
  # Value 0 is used for common event and map event text
  Species           = 1
  Kinds             = 2
  Entries           = 3
  FormNames         = 4
  Moves             = 5
  MoveDescriptions  = 6
  Items             = 7
  ItemPlurals       = 8
  ItemDescriptions  = 9
  Abilities         = 10
  AbilityDescs      = 11
  Types             = 12
  TrainerTypes      = 13
  TrainerNames      = 14
  BeginSpeech       = 15
  EndSpeechWin      = 16
  EndSpeechLose     = 17
  RegionNames       = 18
  PlaceNames        = 19
  PlaceDescriptions = 20
  MapNames          = 21
  PhoneMessages     = 22
  ScriptTexts       = 23
  ContestMoves      = 24
  ContestMoveDescriptions = 25
  @@messages         = Messages.new
  @@messagesFallback = Messages.new("Data/messages.dat",true)

  def self.stringToKey(str)
    return Messages.stringToKey(str)
  end

  def self.normalizeValue(value)
    return Messages.normalizeValue(value)
  end

  def self.denormalizeValue(value)
    Messages.denormalizeValue(value)
  end

  def self.writeObject(f,msgs,secname)
    Messages.denormalizeValue(str)
  end

  def self.extract(outfile)
    @@messages.extract(outfile)
  end

  def self.setMessages(type,array)
    @@messages.setMessages(type,array)
  end

  def self.createHash(type,array)
    Messages.createHash(type,array)
  end

  def self.addMapMessagesAsHash(type,array)
    @@messages.addMapMessagesAsHash(type,array)
  end

  def self.setMapMessagesAsHash(type,array)
    @@messages.setMapMessagesAsHash(type,array)
  end

  def self.addMessagesAsHash(type,array)
    @@messages.addMessagesAsHash(type,array)
  end

  def self.setMessagesAsHash(type,array)
    @@messages.setMessagesAsHash(type,array)
  end

  def self.saveMessages(filename=nil)
    @@messages.saveMessages(filename)
  end

  def self.loadMessageFile(filename)
    @@messages.loadMessageFile(filename)
  end

  def self.get(type,id)
    ret=@@messages.get(type,id)
    if ret==""
      ret=@@messagesFallback.get(type,id)
    end
    return ret
  end

  def self.getCount(type)
    c1=@@messages.getCount(type)
    c2=@@messagesFallback.getCount(type)
    return c1>c2 ? c1 : c2
  end

  def self.getOriginal(type,id)
    return @@messagesFallback.get(type,id)
  end

  def self.getFromHash(type,key)
    @@messages.getFromHash(type,key)
  end

  def self.getFromMapHash(type,key)
    @@messages.getFromMapHash(type,key)
  end
end



def pbLoadMessages(file)
  return MessageTypes.loadMessageFile(file)
end

def pbGetMessageCount(type)
  return MessageTypes.getCount(type)
end

def pbGetMessage(type,id)
  return MessageTypes.get(type,id)
end

def pbGetMessageFromHash(type,id)
  return MessageTypes.getFromHash(type,id)
end

# Replaces first argument with a localized version and formats the other
# parameters by replacing {1}, {2}, etc. with those placeholders.
def _INTL(*arg)
  begin
    string=MessageTypes.getFromHash(MessageTypes::ScriptTexts,arg[0])
  rescue
    string=arg[0]
  end
  string=string.clone
  for i in 1...arg.length
    string.gsub!(/\{#{i}\}/,"#{arg[i]}")
  end
  return string
end

# Replaces first argument with a localized version and formats the other
# parameters by replacing {1}, {2}, etc. with those placeholders.
# This version acts more like sprintf, supports e.g. {1:d} or {2:s}
def _ISPRINTF(*arg)
  begin
    string=MessageTypes.getFromHash(MessageTypes::ScriptTexts,arg[0])
  rescue
    string=arg[0]
  end
  string=string.clone
  for i in 1...arg.length
    string.gsub!(/\{#{i}\:([^\}]+?)\}/){|m|
       next sprintf("%"+$1,arg[i])
    }
  end
  return string
end

def _I(str)
  return _MAPINTL($game_map.map_id,str)
end

def _MAPINTL(mapid,*arg)
  string=MessageTypes.getFromMapHash(mapid,arg[0])
  string=string.clone
  for i in 1...arg.length
    string.gsub!(/\{#{i}\}/,"#{arg[i]}")
  end
  return string
end

def _MAPISPRINTF(mapid,*arg)
  string=MessageTypes.getFromMapHash(mapid,arg[0])
  string=string.clone
  for i in 1...arg.length
    string.gsub!(/\{#{i}\:([^\}]+?)\}/){|m|
       next sprintf("%"+$1,arg[i])
    }
  end
  return string
end

Again don't forget to use Thread Tools Show Printable Version.
 

mewlover22

Pokemon Creator
455
Posts
15
Years
Will all of this make the script work right when it gets to loading round one and two other questions one how do we make the pokebolocks work and how do we set it up so people can see what type of contest move it is?
 
31
Posts
8
Years
Yeah it should all work right.
I am uploading it to my google drive account
https://drive.google.com/file/d/0B7-78oA2YokuZXowNV9reG9yWnM/view?usp=sharing
It is v.16.1 with all the fixes and changes in a fresh download of Pokemon Essentials v16.1
This one includes The Elite Battle System, 6 Gen Project (All Pokémon (721), All The Items (All items I have so you will not have one on the list and I am still working on the Pokéblock Case)), Show Species updated to work with the animated battlers, and Pokémon Following.
This is all required if you want the animated battlers.
(And Pokémon Following script isn't required, but I just included anyways.)

Also there are still some problems with the Contest Script like sometimes when your pokemon should be the winner it isn't and I don't know how to fix.
I had pikachu in the cool contest and squirtle won even though the bar shows pikachu had more points and should have been the winner...
And I am sure there are still other problems with the script, but the person who started this doesn't seem to want to work on any of it.
 
Last edited:

mewlover22

Pokemon Creator
455
Posts
15
Years
It works on the version i have i just need to know hoe to get pokeblocks to work right and i figured out how to make the summary screen show contest move type buy changing a few things from the contest kit when i copy over the storage and summary stuff.
 
Last edited:
31
Posts
8
Years
All I know is that you add the Berry Item Effects to PItem_ItemEffects under the BattleUseOnPokemon handlers (at the bottom of that list is where I put it). And that is the pokeblocks effects. The current problem is no one has finished the pokeblock case or done the conditions summary screen so that you can see the pokeblocks effects on your pokemon.

It looks like it is being used
Code:
  case @contestType
  when "Cool"
    @prelim1+=20 if isConst?($Trainer.party[$game_variables[36]].item,PBItems,:REDSCARF)
    @prelim1+=($Trainer.party[$game_variables[36]].cool/8).floor
  when "Beauty"
    @prelim1+=20 if isConst?($Trainer.party[$game_variables[36]].item,PBItems,:BLUESCARF)
    @prelim1+=($Trainer.party[$game_variables[36]].beauty/8).floor
  when "Smart"
    @prelim1+=20 if isConst?($Trainer.party[$game_variables[36]].item,PBItems,:GREENSCARF)
    @prelim1+=($Trainer.party[$game_variables[36]].smart/8).floor
  when "Tough"
    @prelim1+=20 if isConst?($Trainer.party[$game_variables[36]].item,PBItems,:YELLOWSCARF)
    @prelim1+=($Trainer.party[$game_variables[36]].tough/8).floor
  when "Cute"
    @prelim1+=20 if isConst?($Trainer.party[$game_variables[36]].item,PBItems,:PINKSCARF)  
    @prelim1+=($Trainer.party[$game_variables[36]].cute/8).floor
  end

I just thought about it and and we may need to change all the pokemon.cool, pokemon.beauty, pokemon.cute, pokemon.smart, and pokemon.tough to the variable being used or set it to it's own variables and tweek the script for the new variables under the same area of the contest script....
I am unsure if the pokeblocks really are being taken into account as is...
 
Last edited:

mewlover22

Pokemon Creator
455
Posts
15
Years
mej71 has them set up right but there's no summary screen for them you can use them on the poekmon but idk what they do as it's using the default text from gen 3.
 

Pokébook1

Marene
114
Posts
8
Years
I know it is to late to write here because it passed maybe a month but I have got problems with this script, I got this error message:

Spoiler:
 
1,224
Posts
10
Years
I know it is to late to write here because it passed maybe a month but I have got problems with this script, I got this error message:

Spoiler:

The method egg? no longer exists in Essentials, and was replaced with isEgg?
 
155
Posts
9
Years
  • Age 31
  • Seen Jun 11, 2021
I know it is to late to write here because it passed maybe a month but I have got problems with this script, I got this error message:

Spoiler:
You need to replace every instance of "egg?" to "isEgg?". That should be it.
 
Last edited:

Pokébook1

Marene
114
Posts
8
Years
The method egg? no longer exists in Essentials, and was replaced with isEgg?
I replaced "egg?" with "isEgg?" in PokeBattle_Battler but when I playtest and go inside the Contest Hall and talk to the lady in front of the desk, the screen turns black and this error message pops up:

Spoiler:


I already searched pbExecuteScript in the Script section but I couldn't find it :(
If you know where I must replace it, it would be great and I use the newest Essentials and I don't know if this script supports the new Essentials. Since those scripts have no "isEgg?" in it.
 

Zeak6464

Zeak #3205 - Discord
1,101
Posts
10
Years
  • Age 31
  • USA
  • Seen Oct 9, 2023
I replaced "egg?" with "isEgg?" in PokeBattle_Battler but when I playtest and go inside the Contest Hall and talk to the lady in front of the desk, the screen turns black and this error message pops up:

Spoiler:


I already searched pbExecuteScript in the Script section but I couldn't find it :(
If you know where I must replace it, it would be great and I use the newest Essentials and I don't know if this script supports the new Essentials. Since those scripts have no "isEgg?" in it.

pbChoosePokemon(36,2,proc {|poke|!poke.egg? && !(poke.isShadow? rescue false) && !poke.hasRibbon?(4)})

replace the poke.egg? to poke.isEgg?
 

Maruno

Lead Dev of Pokémon Essentials
5,285
Posts
16
Years
Because Zeak didn't say so, that line of code is actually in an event, not in the scripts. Specifically, the desk lady's event.
 

Pokébook1

Marene
114
Posts
8
Years
pbChoosePokemon(36,2,proc {|poke|!poke.egg? && !(poke.isShadow? rescue false) && !poke.hasRibbon?(4)})

replace the poke.egg? to poke.isEgg?

I searched in the Script editor for "pbChoosePokemon" and could not find the part "egg?" but there just says "isEgg?". Can you please tell me where the section is where I have to replace it.

Thanks in advance
 
Back
Top