The PokéCommunity Forums Fan Games Game Development Scripts, Tutorials & Tools
Essentials Script Plug-and-play Delta Pokemon/Alolan Forms script

Scripts, Tutorials & Tools This forum is for scripts and code, as well as all kinds of tutorials, software, tools and so forth. Remember to give credit!
The thread revival limit does not apply here.

Reply
 
Thread Tools
  #1    
Old August 3rd, 2016 (9:50 PM). Edited May 2nd, 2017 by Rot8er_ConeX.
Rot8er_ConeX's Avatar
Rot8er_ConeX Rot8er_ConeX is offline
     
    Join Date: May 2015
    Location: The Dissa Region
    Gender: Male
    Posts: 822
    This script allows players to make Delta Pokemon (as fans have called them for a while) or Alolan Forms (as they are now officially known) without making them unique species or numbered forms.

    This script includes all of the differences between Alolan Pokemon and their "Kantonian" counterparts Hau uses the word "Kantonian" to describe the player's mother's Meowth, which leads me to believe this is the proper way to refer to the non-Alolan form of a Pokemon that has an Alolan Form. This includes:
    - Types
    - Base stats, if they're different
    - Height and Weight, if they're different
    - Level-up moveset, if they're different
    - TM/Move Tutor compatability
    - Egg Moves
    - Evolution methods, if they're different

    In addition, this script includes the breeding mechanics used in Sun and Moon to enable Kantonian Form parents to birth Kantonian Form children despite the children being born in Alola, just flipped on their end to allow Alolan Form parents to birth Alolan Form children despite the game (presumably) not taking place in Alola.

    I have also included a (logical) method of making the Wormadam-esque Alolan Forms - Raichu, Exeggutor, and Marowak - able to evolve from their non-Alolan pre-evolutions. This does require you to have the Strange Souvenir item in your game.

    The script includes all of the canon Alolan Forms.

    To use, put this code in a script section above Main, but below PSystem_Utilities. If using the EBS and/or Following Pokemon, place it below those scripts but above Main. If using KleinStudio's BW Essentials kit, paste it in a script section directly above Main.

    Code:
    #########################################################################
    # Delta Pokemon/Alolan Form code
    # This is compatible with Essentials v16.2
    # Also compatible with Luka's Elite Battle System (EBS),
    #    Klien's BW Essentials kit,
    #    and mej's Following Pokemon script
    # Note that this code adds the Alolan forms as code within the game
    # It does not automatically create the Alolan forms as possible
    #    encounters.
    # You as the game developer need to decide how you want players to
    #    encounter the Alolan Pokemon.
    #########################################################################
    # To use
    # 1.) place in a new script section below "PSystem_Utilities" but
    #    above "Main"
    #  - if using the EBS or Following Pokemon scripts, place below those
    #      scripts as well as "PSystem_Utilities"
    # 2.) Decide how you want the player to encounter Delta/Alolan Pokemon
    #  - see the bottom of this script for an example that makes Alolan
    #      Exeggutor appear on a certain map
    #########################################################################
    # Please note that the breeding mechanics for Deltaness work under the
    #    assumption that your fangame will NOT be taking place in Alola.
    # Likewise, the evolution mechanics for Pikachu, Cubone, and Exeggcute
    #    work under the assumption that your fangame will NOT be taking
    #    place in Alola, but that you DO wish the players to be able to
    #    obtain Alolan Raichu, Alolan Marowak, and Alolan Exeggutor in
    #    some way.
    #########################################################################
    
    # Battlers
    
    class PokeBattle_Battler
      def isDelta?
        return (@pokemon) ? @pokemon.isDelta? : false
      end
    
      def isAlolan?
        return (@pokemon) ? @pokemon.isDelta? : false
      end
    
      def isEgg?
        return (@pokemon) ? (@pokemon.isEgg? rescue @pokemon.egg? rescue false) : false
      end
    
      def isAlolaForm?
        return (@pokemon) ? @pokemon.isDelta? : false
      end
    end
    
    class PokeBattle_FakeBattler
      def isDelta?; return @pokemon.isDelta?; end
      def isAlolan?; return @pokemon.isDelta?; end
      def isAlolaForm?; return @pokemon.isDelta?; end
    end
    
    # Pokemon
    
    class PokeBattle_Pokemon
      alias ____mf_getAbilityList getAbilityList
      def getAbilityList
        v=MultipleForms.call("getAbilityList",self)
        return v if v!=nil && v.length>0
        return self.____mf_getAbilityList
      end
      
      # generates the list of Egg Moves
      def possibleEggMoves
        v=MultipleForms.call("possibleEggMoves",self)
        return v if v!=nil
        pbRgssOpen("Data/eggEmerald.dat","rb"){|f|
             f.pos=(self.species-1)*8
             offset=f.fgetdw
             length=f.fgetdw
             if length>0
               bob=[]
               f.pos=offset
               i=0; loop do break unless i<length
                 atk=f.fgetw
                 bob.push(atk)
                 i+=1
               end
               return bob
             else
               return []
             end
           }
      end
    
      attr_accessor(:deltaflag)  # Forces the deltaness (true/false)
    
      def isDelta?
        return @deltaflag if @deltaflag != nil
            return false
      end
    
      def isAlolan?
        return isDelta?
      end
    
      def isAlolaForm?
        return isDelta?
      end
      
      def makeDelta
        @deltaflag=true
      end
    
      # provides a fix for forms crashing game
      def spoofForm(val)
        @deltaflag = false
        @form = val
      end
    end
    
    # Breeding
    def pbDayCareGenerateEgg
      if pbDayCareDeposited!=2
        return
      elsif $Trainer.party.length>=6
        raise _INTL("Can't store the egg")
      end
      pokemon0=$PokemonGlobal.daycare[0][0]
      pokemon1=$PokemonGlobal.daycare[1][0]
      mother=nil
      father=nil
      babyspecies=0
      ditto0=pbIsDitto?(pokemon0)
      ditto1=pbIsDitto?(pokemon1)
      if (pokemon0.isFemale? || ditto0)
        babyspecies=(ditto0) ? pokemon1.species : pokemon0.species
        mother=pokemon0
        father=pokemon1
      else
        babyspecies=(ditto1) ? pokemon0.species : pokemon1.species
        mother=pokemon1
        father=pokemon0
      end
      babyspecies=pbGetBabySpecies(babyspecies,mother.item,father.item)
      if isConst?(babyspecies,PBSpecies,:MANAPHY) && hasConst?(PBSpecies,:PHIONE)
        babyspecies=getConst(PBSpecies,:PHIONE)
      elsif (isConst?(babyspecies,PBSpecies,:NIDORANfE) && hasConst?(PBSpecies,:NIDORANmA)) ||
            (isConst?(babyspecies,PBSpecies,:NIDORANmA) && hasConst?(PBSpecies,:NIDORANfE))
        babyspecies=[getConst(PBSpecies,:NIDORANmA),
                     getConst(PBSpecies,:NIDORANfE)][rand(2)]
      elsif (isConst?(babyspecies,PBSpecies,:VOLBEAT) && hasConst?(PBSpecies,:ILLUMISE)) ||
            (isConst?(babyspecies,PBSpecies,:ILLUMISE) && hasConst?(PBSpecies,:VOLBEAT))
        babyspecies=[getConst(PBSpecies,:VOLBEAT),
                     getConst(PBSpecies,:ILLUMISE)][rand(2)]
      end
      # Generate egg
      egg=PokeBattle_Pokemon.new(babyspecies,EGGINITIALLEVEL,$Trainer)
      # Randomise personal ID
      pid=rand(65536)
      pid|=(rand(65536)<<16)
      egg.personalID=pid
      # Inheriting form
      if isConst?(babyspecies,PBSpecies,:BURMY) ||
         isConst?(babyspecies,PBSpecies,:SHELLOS) ||
         isConst?(babyspecies,PBSpecies,:BASCULIN) ||
         isConst?(babyspecies,PBSpecies,:MINIOR) ||
         isConst?(babyspecies,PBSpecies,:ORICORIO)
        egg.form=mother.form
      end
      # Inheriting Delta-ness
      if (mother.isDelta? && isConst?(mother.item,PBItems,:EVERSTONE)) ||
         (mother.isDelta? && isConst?(mother.item,PBItems,:STRANGESOUVENIR)) ||
    	 (father.isDelta? && isConst?(father.item,PBItems,:EVERSTONE)) ||
         (father.isDelta? && isConst?(father.item,PBItems,:STRANGESOUVENIR))
        egg.makeDelta
      end
      # Inheriting Moves
      moves=[]
      othermoves=[] 
      movefather=father; movemother=mother
      if pbIsDitto?(movefather) && !mother.isFemale?
        movefather=mother; movemother=father
      end
      # Initial Moves
      initialmoves=egg.getMoveList
      moop=egg.possibleEggMoves
      for k in initialmoves
        if k[0]<=EGGINITIALLEVEL
          moves.push(k[1])
        else
          othermoves.push(k[1]) if mother.knowsMove?(k[1]) && father.knowsMove?(k[1])
        end
      end
      # Inheriting Natural Moves
      for move in othermoves
        moves.push(move)
      end
      # Inheriting Machine Moves
      if !USENEWBATTLEMECHANICS
        for i in 0...$ItemData.length
          next if !$ItemData[i]
          atk=$ItemData[i][ITEMMACHINE]
          next if !atk || atk==0
          if egg.isCompatibleWithMove?(atk)
            moves.push(atk) if movefather.knowsMove?(atk)
          end
        end
      end
      # Inheriting Egg Moves
      if moop.length>0 && movefather.isMale?
        for i in moop
          moves.push(i) if movefather.knowsMove?(i)
        end
      end
      if USENEWBATTLEMECHANICS && moop.length>0 && movemother.isFemale?
        for i in moop
          moves.push(i) if movemother.knowsMove?(i)
        end
      end
      # Volt Tackle
      lightball=false
      if (isConst?(father.species,PBSpecies,:PIKACHU) || 
          isConst?(father.species,PBSpecies,:RAICHU)) && 
          isConst?(father.item,PBItems,:LIGHTBALL)
        lightball=true
      end
      if (isConst?(mother.species,PBSpecies,:PIKACHU) || 
          isConst?(mother.species,PBSpecies,:RAICHU)) && 
          isConst?(mother.item,PBItems,:LIGHTBALL)
        lightball=true
      end
      if lightball && isConst?(babyspecies,PBSpecies,:PICHU) &&
         hasConst?(PBMoves,:VOLTTACKLE)
        moves.push(getConst(PBMoves,:VOLTTACKLE))
      end
      moves|=[] # remove duplicates
      # Assembling move list
      finalmoves=[]
      listend=moves.length-4
      listend=0 if listend<0
      j=0
      for i in listend..listend+3
        moveid=(i>=moves.length) ? 0 : moves[i]
        finalmoves[j]=PBMove.new(moveid)
        j+=1
      end 
      # Inheriting Individual Values
      ivs=[]
      for i in 0...6
        ivs[i]=rand(32)
      end
      ivinherit=[]
      for i in 0...2
        parent=[mother,father][i]
        ivinherit[i]=PBStats::HP if isConst?(parent.item,PBItems,:POWERWEIGHT)
        ivinherit[i]=PBStats::ATTACK if isConst?(parent.item,PBItems,:POWERBRACER)
        ivinherit[i]=PBStats::DEFENSE if isConst?(parent.item,PBItems,:POWERBELT)
        ivinherit[i]=PBStats::SPEED if isConst?(parent.item,PBItems,:POWERANKLET)
        ivinherit[i]=PBStats::SPATK if isConst?(parent.item,PBItems,:POWERLENS)
        ivinherit[i]=PBStats::SPDEF if isConst?(parent.item,PBItems,:POWERBAND)
      end
      num=0; r=rand(2)
      for i in 0...2
        if ivinherit[r]!=nil
          parent=[mother,father][r]
          ivs[ivinherit[r]]=parent.iv[ivinherit[r]]
          num+=1
          break
        end
        r=(r+1)%2
      end
      stats=[PBStats::HP,PBStats::ATTACK,PBStats::DEFENSE,
             PBStats::SPEED,PBStats::SPATK,PBStats::SPDEF]
      limit=(USENEWBATTLEMECHANICS && (isConst?(mother.item,PBItems,:DESTINYKNOT) ||
             isConst?(father.item,PBItems,:DESTINYKNOT))) ? 5 : 3
      loop do
        freestats=[]
        for i in stats
          freestats.push(i) if !ivinherit.include?(i)
        end
        break if freestats.length==0
        r=freestats[rand(freestats.length)]
        parent=[mother,father][rand(2)]
        ivs[r]=parent.iv[r]
        ivinherit.push(r)
        num+=1
        break if num>=limit
      end
      # Inheriting nature
      newnatures=[]
      newnatures.push(mother.nature) if isConst?(mother.item,PBItems,:EVERSTONE)
      newnatures.push(father.nature) if isConst?(father.item,PBItems,:EVERSTONE)
      if newnatures.length>0
        egg.setNature(newnatures[rand(newnatures.length)])
      end
      # Masuda method and Shiny Charm
      shinyretries=0
      shinyretries+=5 if father.language!=mother.language
      shinyretries+=2 if hasConst?(PBItems,:SHINYCHARM) &&
                         $PokemonBag.pbQuantity(:SHINYCHARM)>0
      if shinyretries>0
        for i in 0...shinyretries
          break if egg.isShiny?
          egg.personalID=rand(65536)|(rand(65536)<<16)
        end
      end
      # Inheriting ability from the mother
      if (!ditto0 && !ditto1)
        if mother.hasHiddenAbility?
          egg.setAbility(mother.abilityIndex) if rand(10)<6
        else
          if rand(10)<8
            egg.setAbility(mother.abilityIndex)
          else
            egg.setAbility((mother.abilityIndex+1)%2)
          end
        end
      elsif ((!ditto0 && ditto1) || (!ditto1 && ditto0)) && USENEWBATTLEMECHANICS
        parent=(!ditto0) ? mother : father
        if parent.hasHiddenAbility?
          egg.setAbility(parent.abilityIndex) if rand(10)<6
        end
      end
      # Inheriting Poké Ball from the mother
      if mother.isFemale? &&
         !isConst?(pbBallTypeToBall(mother.ballused),PBItems,:MASTERBALL) &&
         !isConst?(pbBallTypeToBall(mother.ballused),PBItems,:CHERISHBALL)
        egg.ballused=mother.ballused
      end
      egg.iv[0]=ivs[0]
      egg.iv[1]=ivs[1]
      egg.iv[2]=ivs[2]
      egg.iv[3]=ivs[3]
      egg.iv[4]=ivs[4]
      egg.iv[5]=ivs[5]
      egg.moves[0]=finalmoves[0]
      egg.moves[1]=finalmoves[1]
      egg.moves[2]=finalmoves[2]
      egg.moves[3]=finalmoves[3]
      egg.calcStats
      egg.obtainText=_INTL("Day-Care Couple")
      egg.name=_INTL("Egg")
      dexdata=pbOpenDexData
      pbDexDataOffset(dexdata,babyspecies,21)
      eggsteps=dexdata.fgetw
      dexdata.close
      egg.eggsteps=eggsteps
      if rand(65536)<POKERUSCHANCE
        egg.givePokerus
      end
      $Trainer.party[$Trainer.party.length]=egg
    end
    
    ##############################################################
    # Appearance change
    ##############################################################
    class PokemonSprite < SpriteWrapper
      def setSpeciesBitmap(species,female=false,form=0,shiny=false,shadow=false,back=false,egg=false,delta=false)
        @_iconbitmap.dispose if @_iconbitmap
        @_iconbitmap=species>0 ? pbLoadSpeciesBitmap(species,female,form,shiny,shadow,back,egg,delta) : nil
        [email protected]_iconbitmap ? @_iconbitmap.bitmap : nil
      end
    end
    
    class PokemonEggHatchScene
      def pbStartScene(pokemon)
        @sprites={}
        @pokemon=pokemon
        @nicknamed=false
        @viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
        @viewport.z=99999
        addBackgroundOrColoredPlane(@sprites,"background","hatchbg",
          Color.new(248,248,248),@viewport)
        @sprites["pokemon"]=PokemonSprite.new(@viewport)
        @sprites["pokemon"].setSpeciesBitmap(@pokemon.species,@pokemon.isFemale?,
                                            (@pokemon.form rescue 0),@pokemon.isShiny?,
                                            false,false,true,(@pokemon.isDelta? rescue false)) # Egg sprite
        @sprites["pokemon"].x=Graphics.width/[email protected]["pokemon"].bitmap.width/2
        @sprites["pokemon"].y=48+([email protected]["pokemon"].bitmap.height)/2
        @sprites["hatch"]=BitmapSprite.new(Graphics.width,Graphics.height,@viewport)
        @sprites["overlay"]=BitmapSprite.new(Graphics.width,Graphics.height,@viewport)
        @sprites["overlay"].z=200
        @sprites["overlay"].bitmap=Bitmap.new(Graphics.width,Graphics.height)
        @sprites["overlay"].bitmap.fill_rect(0,0,Graphics.width,Graphics.height,
            Color.new(255,255,255))
        @sprites["overlay"].opacity=0
        pbFadeInAndShow(@sprites)
      end
    end
    
    def pbLoadPokemonBitmap(pokemon, back=false, scale=nil)
      return pbLoadPokemonBitmapSpecies(pokemon,pokemon.species,back,scale)
    end
    
    # Note: Returns an AnimatedBitmap, not a Bitmap
    def pbLoadPokemonBitmapSpecies(pokemon, species, back=false, scale=nil)
      ret=nil
      if scale==nil
        scale=1
        if defined?(POKEMONSPRITESCALE)
          scale=POKEMONSPRITESCALE if POKEMONSPRITESCALE != nil
        end
      end
      if pokemon.isEgg?
        bitmapFileName=sprintf("Graphics/Battlers/%segg",getConstantName(PBSpecies,species)) rescue nil
        if !pbResolveBitmap(bitmapFileName)
          bitmapFileName=sprintf("Graphics/Battlers/%03degg",species)
          if !pbResolveBitmap(bitmapFileName)
            bitmapFileName=sprintf("Graphics/Battlers/egg")
          end
        end
        bitmapFileName=pbResolveBitmap(bitmapFileName)
      else
        bitmapFileName=pbCheckPokemonBitmapFiles([species,back,
                                                  (pokemon.isFemale?),
                                                  pokemon.isShiny?,
                                                  (pokemon.form rescue 0),
                                                  (pokemon.isShadow? rescue false),
                                                  (pokemon.isDelta? rescue false)])
        # Alter bitmap if supported
        alterBitmap=(MultipleForms.getFunction(species,"alterBitmap") rescue nil)
      end
      if bitmapFileName && alterBitmap
        animatedBitmap=AnimatedBitmap.new(bitmapFileName)
        copiedBitmap=animatedBitmap.copy
        animatedBitmap.dispose
        copiedBitmap.each {|bitmap|
          alterBitmap.call(pokemon,bitmap)
        }
        ret=copiedBitmap
        if defined?(DynamicPokemonSprite) # if EBS code exists
          animatedBitmap=AnimatedBitmapWrapper.new(bitmapFileName,scale)
          animatedBitmap.prepareStrip
          for i in 0...animatedBitmap.totalFrames
            alterBitmap.call(pokemon,animatedBitmap.alterBitmap(i))
          end
          animatedBitmap.compileStrip
          ret=animatedBitmap
        end
      elsif bitmapFileName
        ret=AnimatedBitmap.new(bitmapFileName)
        ret=AnimatedBitmapWrapper.new(bitmapFileName,scale) if defined?(DynamicPokemonSprite) # if EBS code exists
      end
      return ret
    end
    
    # Note: Returns an AnimatedBitmap, not a Bitmap
    def pbLoadSpeciesBitmap(species,female=false,form=0,shiny=false,shadow=false,back=false,egg=false,delta=false)
      ret=nil
      if egg
        bitmapFileName=sprintf("Graphics/Battlers/%segg",getConstantName(PBSpecies,species)) rescue nil
        if !pbResolveBitmap(bitmapFileName)
          bitmapFileName=sprintf("Graphics/Battlers/%03degg",species)
          if !pbResolveBitmap(bitmapFileName)
            bitmapFileName=sprintf("Graphics/Battlers/egg")
          end
        end
        bitmapFileName=pbResolveBitmap(bitmapFileName)
      else
        bitmapFileName=pbCheckPokemonBitmapFiles([species,back,female,shiny,form,shadow,delta])
      end
      if bitmapFileName
        ret=AnimatedBitmap.new(bitmapFileName)
      end
      return ret
    end
    
    def pbCheckPokemonBitmapFiles(params)
      species=params[0]
      back=params[1]
      factors=[]
      factors.push([5,params[5],false]) if params[5] && params[5]!=false    # shadow
      factors.push([2,params[2],false]) if params[2] && params[2]!=false    # gender
      factors.push([3,params[3],false]) if params[3] && params[3]!=false    # shiny
      factors.push([4,params[4].to_s,""]) if params[4] && params[4].to_s!="" &&
                                                          params[4].to_s!="0" # form
      factors.push([6,params[6],false]) if params[6] && params[6]!=false    # shiny
      tshadow=false
      tgender=false
      tshiny=false
      tdelta=false
      tform=""
      for i in 0...2**factors.length
        for j in 0...factors.length
          case factors[j][0]
          when 2  # gender
            tgender=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 3  # shiny
            tshiny=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 4  # form
            tform=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 5  # shadow
            tshadow=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 6  # delta
            tdelta=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          end
        end
        folder=""
        if defined?(DUALSCREENHEIGHT) # if BW data exists
          folder="Front/"
          folder="Back/" if back
          folder="FrontShiny/" if tshiny
          folder="BackShiny/" if back && tshiny
          folder+="Female/" if tgender
        end
        bitmapFileName=sprintf("Graphics/Battlers/%s%s%s%s%s%s%s%s",
          folder,
          getConstantName(PBSpecies,species),
          tgender ? "f" : "",
          tshiny ? "s" : "",
          tdelta ? "d" : "",
          back ? "b" : "",
          (tform!="" ? "_"+tform : ""),
          tshadow ? "_shadow" : "") rescue nil
        ret=pbResolveBitmap(bitmapFileName)
        return ret if ret
        bitmapFileName=sprintf("Graphics/Battlers/%s%03d%s%s%s%s%s%s",
          folder, species,
          tgender ? "f" : "",
          tshiny ? "s" : "",
          tdelta ? "d" : "",
          back ? "b" : "",
          (tform!="" ? "_"+tform : ""),
          tshadow ? "_shadow" : "")
        ret=pbResolveBitmap(bitmapFileName)
        return ret if ret
      end
      return nil
    end
    
    def pbPokemonIconFile(pokemon)
      bitmapFileName=nil
      bitmapFileName=pbCheckPokemonIconFiles([pokemon.species,
                                              (pokemon.isFemale?),
                                              pokemon.isShiny?,
                                              (pokemon.form rescue 0),
                                              (pokemon.isShadow? rescue false),
                                              pokemon.isDelta?],
                                              pokemon.isEgg?)
      return bitmapFileName
    end
    
    def pbCheckPokemonIconFiles(params,egg=false)
      species=params[0]
      if egg
        bitmapFileName=sprintf("Graphics/Icons/icon%segg",getConstantName(PBSpecies,species)) rescue nil
        if !pbResolveBitmap(bitmapFileName)
          bitmapFileName=sprintf("Graphics/Icons/icon%03degg",species)
          if !pbResolveBitmap(bitmapFileName)
            bitmapFileName=sprintf("Graphics/Icons/iconEgg")
          end
        end
        return pbResolveBitmap(bitmapFileName)
      else
        factors=[]
        factors.push([4,params[4],false]) if params[4] && params[4]!=false    # shadow
        factors.push([1,params[1],false]) if params[1] && params[1]!=false    # gender
        factors.push([2,params[2],false]) if params[2] && params[2]!=false    # shiny
        factors.push([5,params[5],false]) if params[5] && params[5]!=false    # delta
        factors.push([3,params[3].to_s,""]) if params[3] && params[3].to_s!="" &&
                                                            params[3].to_s!="0" # form
        tshadow=false
        tgender=false
        tshiny=false
        tdelta=false
        tform=""
        for i in 0...2**factors.length
          for j in 0...factors.length
            case factors[j][0]
            when 1  # gender
              tgender=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
            when 2  # shiny
              tshiny=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
            when 3  # form
              tform=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
            when 4  # shadow
              tshadow=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
            when 5  # delta
              tdelta=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
            end
          end
          bitmapFileName=sprintf("Graphics/Icons/icon%s%s%s%s%s%s",
            getConstantName(PBSpecies,species),
            tgender ? "f" : "",
            tshiny ? "s" : "",
            tdelta ? "d" : "",
            (tform!="" ? "_"+tform : ""),
            tshadow ? "_shadow" : "") rescue nil
          ret=pbResolveBitmap(bitmapFileName)
          return ret if ret
          bitmapFileName=sprintf("Graphics/Icons/icon%03d%s%s%s%s%s",
            species,
            tgender ? "f" : "",
            tshiny ? "s" : "",
            tdelta ? "d" : "",
            (tform!="" ? "_"+tform : ""),
            tshadow ? "_shadow" : "")
          ret=pbResolveBitmap(bitmapFileName)
          return ret if ret
        end
      end
      return nil
    end
    
    #########################################################################
    # Following Pokemon compatibility
    #########################################################################
    class DependentEvents
      def change_sprite(id, shiny=nil, animation=nil, form=nil, gender=nil, shadow=false, delta=nil)
        events=$PokemonGlobal.dependentEvents
        for i in 0...events.length
          if events[i] && events[i][8]=="Dependent"
            file=FOLLOWER_FILE_DIR+pbCheckPokemonFollowerFiles([id,gender,shiny,delta,form,shadow])
            events[i][6]=file
            @realEvents[i].character_name=file
            if animation
              $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
            end
            $game_variables[Walking_Time_Variable]=0
          end
        end
      end
    
      def refresh_sprite(animation=true)
        if $game_variables[Current_Following_Variable]!=0
          return unless $game_switches[Toggle_Following_Switch]
          return if $PokemonGlobal.bicycle
          if $Trainer.party[0].isShiny?
            shiny=true
          else
            shiny=false
          end
          if defined?($Trainer.party[0].isDelta?)
            delta = $Trainer.party[0].isDelta?
          else
            delta = false
          end
          if $Trainer.party[0].form>0
            form=$Trainer.party[0].form
          else
            form=nil
          end
          if defined?($Trainer.party[0].isShadow?)
            shadow = $Trainer.party[0].isShadow?
          else
            shadow = false
          end
          if $PokemonGlobal.surfing
            if $Trainer.party[0].hp>0 && !$Trainer.party[0].isEgg? && $Trainer.party[0].hasType?(:WATER)
              events=$PokemonGlobal.dependentEvents
              if animation
                for i in 0...events.length
                  $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
                  pbWait(10)
                end
              end
              change_sprite($Trainer.party[0].species, shiny, false, form, $Trainer.party[0].gender, shadow, delta)
            elsif ALWAYS_ANIMATED_CAN_SURF && ($Trainer.party[0].hasType?(:FLYING) ||
              isConst?($Trainer.party[0].ability,PBAbilities,:LEVITATE) ||
              ALWAYS_ANIMATED_FOLLOWERS.include?($Trainer.party[0].species)) &&
              !(ALWAYS_ANIMATED_EXCEPTION.include?($Trainer.party[0].species)) &&
              $Trainer.party[0].hp>0 && !$Trainer.party[0].isEgg?
              events=$PokemonGlobal.dependentEvents
              if animation
                for i in 0...events.length
                  $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
                  pbWait(10)
                end
              end
              change_sprite($Trainer.party[0].species, shiny, false, form, $Trainer.party[0].gender, shadow, delta)
            else
              remove_sprite(false)
            end
          elsif $PokemonGlobal.diving
            if $Trainer.party[0].hp>0 && !$Trainer.party[0].isEgg? && $Trainer.party[0].hasType?(:WATER) && WATERPOKEMONCANDIVE
              events=$PokemonGlobal.dependentEvents
              if animation
                for i in 0...events.length
                  $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
                  pbWait(10)
                end
              end
              change_sprite($Trainer.party[0].species, shiny, false, form, $Trainer.party[0].gender, shadow, delta)
            else
              remove_sprite(false)
            end
          else
            if $Trainer.party[0].hp>0 && !$Trainer.party[0].isEgg? && $scene.is_a?(Scene_Map)
              events=$PokemonGlobal.dependentEvents
              if animation
                for i in 0...events.length
                  $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
                  pbWait(10)
                end
              end
              change_sprite($Trainer.party[0].species, shiny, false, form, $Trainer.party[0].gender, shadow, delta)
            elsif $Trainer.party[0].hp<=0 || $Trainer.party[0].isEgg?
              remove_sprite(animation)
            end
          end
        else
          check_faint
        end
      end
    
      def Come_back(shiny=nil, animation=nil, delta=nil)
        return if !$game_variables[Following_Activated_Switch]
        return if $Trainer.party.length==0
        $PokemonTemp.dependentEvents.pbMoveDependentEvents
        events=$PokemonGlobal.dependentEvents
        if $game_variables[Current_Following_Variable]==$Trainer.party[0]
          remove_sprite(false)
          if $scene.is_a?(Scene_Map)
            for i in 0...events.length
              $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
            end
          end
        end
        if $Trainer.party[0].hp>0 && !$Trainer.party[0].isEgg?
          $game_variables[Current_Following_Variable]=$Trainer.party[0]
          refresh_sprite(animation)
        end
        for i in 0...events.length
          if events[i] && events[i][8]=="Dependent"
            file=FOLLOWER_FILE_DIR+pbCheckPokemonFollowerFiles([id,gender,shiny,delta,form,shadow])
            events[i][6]=file
            @realEvents[i].character_name=file
            if animation
              $scene.spriteset.addUserAnimation(Animation_Come_Out,@realEvents[i].x,@realEvents[i].y)
            end
          end
        end
      end
    end
    
    # this is an entirely new function, not found in the official release of Following Pokemon
    # it searches for Follower sprites the same way base Essentials searches for battlers and icons
    # rather than a series of "if-than" events
    def pbCheckPokemonFollowerFiles(params)
      species=params[0]
      factors=[]
      factors.push([1,params[1],false]) if params[1] && params[1]!=false    # gender
      factors.push([2,params[2],false]) if params[2] && params[2]!=false    # shiny
      factors.push([3,params[3],false]) if params[3] && params[3]!=false    # delta
      factors.push([4,params[4].to_s,""]) if params[4] && params[4].to_s!="" # form
      factors.push([5,params[5],false]) if params[5] && params[5]!=false    # shadow
      tshadow=false
      tgender=false
      tshiny=false
      tdelta=false
      tform=""
      for i in 0...2**factors.length
        for j in 0...factors.length
          case factors[j][0]
          when 1  # gender
            tgender=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 2  # shiny
            tshiny=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 3  # delta
            tdelta=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 4  # form
            tform=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          when 5  # shadow
            tshadow=((i/(2**j))%2==0) ? factors[j][1] : factors[j][2]
          end
        end
        bitmapFileName=sprintf("%s%s%s%s%s%s",
          getConstantName(PBSpecies,species),
          tgender ? "f" : "",
          tshiny ? "s" : "",
          tdelta ? "d" : "",
          (tform!="" ? "_"+tform : ""),
          tshadow ? "_shadow" : "") rescue nil
        ret=pbResolveBitmap(sprintf("%s%s%s",FOLLOWER_FILE_PATH,FOLLOWER_FILE_DIR,bitmapFileName))
        return bitmapFileName if ret
        bitmapFileName=sprintf("%03d%s%s%s%s%s",
          species,
          tgender ? "f" : "",
          tshiny ? "s" : "",
          tdelta ? "d" : "",
          (tform!="" ? "_"+tform : ""),
          tshadow ? "_shadow" : "")
        ret=pbResolveBitmap(sprintf("%s%s%s",FOLLOWER_FILE_PATH,FOLLOWER_FILE_DIR,bitmapFileName))
        return bitmapFileName if ret
      end
    end
    
    ##############################################################
    # Hybrid AnimatedBitmapWrapper class to encompass both the
    #    EBS version's inputs and the BW version's ones
    ##############################################################
    class AnimatedBitmapWrapper
      attr_reader :width
      attr_reader :height
      attr_reader :totalFrames
      attr_reader :animationFrames
      attr_reader :currentIndex
      attr_accessor :scale
    
      def initialize(file,twoframe_scale=2)
        raise "filename is nil" if file==nil
        if scale.is_a?(Numeric) # EBS version
          @scale = twoframe_scale
          @twoframe = false
        elsif !!scale == scale # BW version
          @scale = 2
          @twoframe = twoframe_scale
        end
        if @scale==nil
          @scale=2
        end
        @width = 0
        @height = 0
        @frame = 0
        @frames = 2
        @direction = +1
        @animationFinish = false
        @totalFrames = 0
        @currentIndex = 0
        @speed = 1
          # 0 - not moving at all
          # 1 - normal speed
          # 2 - medium speed
          # 3 - slow speed
        bmp = BitmapCache.load_bitmap(file)
        #bmp = Bitmap.new(file)
        @bitmapFile=Bitmap.new(bmp.width,bmp.height); @bitmapFile.blt(0,0,bmp,Rect.new(0,0,bmp.width,bmp.height))
        # initializes full Pokemon bitmap
        @bitmap=Bitmap.new(@bitmapFile.width,@bitmapFile.height)
        @bitmap.blt(0,0,@bitmapFile,Rect.new(0,0,@bitmapFile.width,@bitmapFile.height))
        @[email protected]*@scale
        @[email protected]*@scale
    
        @[email protected]/@bitmap.height
        @[email protected]*@frames
        # calculates total number of frames
        @loop_points=[0,@totalFrames]
        # first value is start, second is end
    
        @actualBitmap=Bitmap.new(@width,@height)
        @actualBitmap.clear
        @actualBitmap.stretch_blt(Rect.new(0,0,@width,@height),@bitmap,Rect.new(@currentIndex*(@width/@scale),0,@width/@scale,@height/@scale))
      end
      alias initialize_elite initialize
    
      def length; @totalFrames; end
      def disposed?; @actualBitmap.disposed?; end
      def dispose; @actualBitmap.dispose; end
      def copy; @actualBitmap.clone; end
      def bitmap; @actualBitmap; end
      def bitmap=(val); @actualBitmap=val; end
      def each; end
      def alterBitmap(index); return @strip[index]; end
    
      def prepareStrip
        @strip=[]
        for i in [email protected]
          bitmap=Bitmap.new(@width,@height)
          bitmap.stretch_blt(Rect.new(0,0,@width,@height),@bitmapFile,Rect.new((@width/@scale)*i,0,@width/@scale,@height/@scale))
          @strip.push(bitmap)
        end
      end
      def compileStrip
        @bitmap.clear
        for i in [email protected]
          @bitmap.stretch_blt(Rect.new((@width/@scale)*i,0,@width/@scale,@height/@scale),@strip[i],Rect.new(0,0,@width,@height))
        end
      end
    
      def reverse
        if @direction  >  0
          @direction=-1
        elsif @direction < 0
          @direction=+1
        end
      end
    
      def setLoop(start, finish)
        @loop_points=[start,finish]
      end
    
      def setSpeed(value)
        @speed=value
      end
    
      def toFrame(frame)
        if frame.is_a?(String)
          if frame=="last"
            [email protected]
          else
            frame=0
          end
        end
        [email protected] if frame > @totalFrames
        frame=0 if frame < 0
        @currentIndex=frame
        @actualBitmap.clear
        @actualBitmap.stretch_blt(Rect.new(0,0,@width,@height),@bitmap,Rect.new(@currentIndex*(@width/@scale),0,@width/@scale,@height/@scale))
      end
    
      def play
        return if @currentIndex >= @loop_points[1]-1
        self.update
      end
    
      def finished?
        return (@[email protected])
      end
    
      def update
        return false if @actualBitmap.disposed?
        return false if @speed < 1
        case @speed
        # frame skip
        when 1
          @frames=2
        when 2
          @frames=4
        when 3
          @frames=5
        end
        @frame+=1
    
        if @frame >[email protected]
          # processes animation speed
          @[email protected]
          @[email protected]_points[0] if @currentIndex >[email protected]_points[1]
          @[email protected]_points[1]-1 if @currentIndex < @loop_points[0]
          @frame=0
        end
        @actualBitmap.clear
        @actualBitmap.stretch_blt(Rect.new(0,0,@width,@height),@bitmap,Rect.new(@currentIndex*(@width/@scale),0,@width/@scale,@height/@scale))
        # updates the actual bitmap
      end
      alias update_elite update
    
      # returns bitmap to original state
      def deanimate
        @frame=0
        @currentIndex=0
        @actualBitmap.clear
        @actualBitmap.stretch_blt(Rect.new(0,0,@width,@height),@bitmap,Rect.new(@currentIndex*(@width/@scale),0,@width/@scale,@height/@scale))
      end
    end
    
    ##############################################################
    # Evolution differences
    ##############################################################
    def pbGetEvolvedFormData(species,delta=false)
      ret=[]
      _EVOTYPEMASK=0x3F
      _EVODATAMASK=0xC0
      _EVONEXTFORM=0x00
      pbRgssOpen("Data/evolutions.dat","rb"){|f|
         f.pos=(species-1)*8
         offset=f.fgetdw
         length=f.fgetdw
         if length>0
           f.pos=offset
           i=0; loop do break unless i<length
             evo=f.fgetb
             evonib=evo&_EVOTYPEMASK
             level=f.fgetw
             poke=f.fgetw
             if (evo&_EVODATAMASK)==_EVONEXTFORM
               ret.push([evonib,level,poke])
             end
             i+=5
           end
         end
      }
      if delta
        ret[0][0]=27 if isConst?(species,PBSpecies,:RATTATA) # Alolan Rattata only evolves at night
        ret[0][0]=1 if isConst?(species,PBSpecies,:MEOWTH) # Alolan Meowth evolves via friendship
        # Alolan Vulpix and Alolan Sandshrew evolve via the Ice Stone if it exists
        ret[0][2]=getConst(PBItems,:ICESTONE) if isConst?(species,PBSpecies,:VULPIX) && getConst(PBItems,:ICESTONE)!=nil
        ret[0][0]=7 if isConst?(species,PBSpecies,:SANDSHREW) && getConst(PBItems,:ICESTONE)!=nil
        ret[0][2]=getConst(PBItems,:ICESTONE) if isConst?(species,PBSpecies,:SANDSHREW) && getConst(PBItems,:ICESTONE)!=nil
      end
      return ret
    end
    
    def pbCheckEvolutionEx(pokemon)
      return -1 if pokemon.species<=0 || pokemon.isEgg?
      return -1 if isConst?(pokemon.species,PBSpecies,:PICHU) && pokemon.form==1
      return -1 if isConst?(pokemon.item,PBItems,:EVERSTONE) &&
                   !isConst?(pokemon.species,PBSpecies,:KADABRA)
      ret=-1
      for form in pbGetEvolvedFormData(pokemon.species,pokemon.isDelta?)
        ret=yield pokemon,form[0],form[1],form[2]
        break if ret>0
      end
      return ret
    end
    
    # Pikachu, Cubone (at night), and Exeggcute holding the Strange Souvenir
    #    will evolve into Alolan Raichu, Alolan Marowak, and Alolan Exeggutor
    #    respectively.  (The item will not be consumed.)
    # Remove this function if you wish this not to be the case.
    class PokemonEvolutionScene
      def pbStartScreen(pokemon,newspecies)
        @sprites={}
        @bgviewport=Viewport.new(0,0,Graphics.width,Graphics.height)
        @bgviewport.z=99999
        @viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
        @viewport.z=99999
        @msgviewport=Viewport.new(0,0,Graphics.width,Graphics.height)
        @msgviewport.z=99999
        @pokemon=pokemon
        @newspecies=newspecies
        addBackgroundOrColoredPlane(@sprites,"background","evolutionbg",
           Color.new(248,248,248),@bgviewport)
        rsprite1=PokemonSprite.new(@viewport)
        rsprite2=PokemonSprite.new(@viewport)
        rsprite1.setPokemonBitmap(@pokemon,false)
        if isConst?(pokemon.item,PBItems,:STRANGESOUVENIR)
          if (isConst?(@newspecies,PBSpecies,:MAROWAK) && PBDayNight.isNight?) ||
              isConst?(@newspecies,PBSpecies,:RAICHU) ||
              isConst?(@newspecies,PBSpecies,:EXEGGUTOR)
            @pokemon.makeDelta
          end
        end
        rsprite2.setPokemonBitmapSpecies(@pokemon,@newspecies,false)
        rsprite1.ox=rsprite1.bitmap.width/2
        rsprite1.oy=rsprite1.bitmap.height/2
        rsprite2.ox=rsprite2.bitmap.width/2
        rsprite2.oy=rsprite2.bitmap.height/2
        rsprite1.x=Graphics.width/2
        rsprite1.y=(Graphics.height-64)/2
        rsprite2.x=rsprite1.x
        rsprite2.y=rsprite1.y
        rsprite2.opacity=0
        @sprites["rsprite1"]=rsprite1
        @sprites["rsprite2"]=rsprite2
        pbGenerateMetafiles(rsprite1.ox,rsprite1.oy,rsprite2.ox,rsprite2.oy)
        @sprites["msgwindow"]=Kernel.pbCreateMessageWindow(@msgviewport)
        pbFadeInAndShow(@sprites) { pbUpdate }
      end
    end
    
    ##############################################################
    # Alolan Form differences
    ##############################################################
    
    MultipleForms.register(:RATTATA,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:GLUTTONY),0],
              [getID(PBAbilities,:HUSTLE),1],
              [getID(PBAbilities,:THICKFAT),2]]
      end
      next
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:TAUNT,:ICEBEAM,
                 :BLIZZARD,:PROTECT,:RAINDANCE,:FRUSTRATION,:RETURN,
                 :SHADOWBALL,:DOUBLETEAM,:SLUDGEBOMB,:TORMENT,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:QUASH,
                 :EMBARGO,:SHADOWCLAW,:GRASSKNOT,:SWAGGER,:SLEEPTALK,
                 :UTURN,:SUBSTITUTE,:SNARL,:DARKPULSE,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:COUNTER,:FINALGAMBIT,:FURYSWIPES,:MEFIRST,:REVENGE,
                 :REVERSAL,:SNATCH,:STOCKPILE,:SWALLOW,:SWITCHEROO,
                 :UPROAR]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:RATICATE,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 25.5 if pokemon.isDelta?
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [75,71,70,77,40,80] if pokemon.isDelta?
       next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:GLUTTONY),0],
              [getID(PBAbilities,:HUSTLE),1],
              [getID(PBAbilities,:THICKFAT),2]]
      end
      next
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:TAUNT,:ICEBEAM,
                 :BLIZZARD,:PROTECT,:RAINDANCE,:FRUSTRATION,:RETURN,
                 :SHADOWBALL,:DOUBLETEAM,:SLUDGEBOMB,:TORMENT,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:QUASH,
                 :EMBARGO,:SHADOWCLAW,:GRASSKNOT,:SWAGGER,:SLEEPTALK,
                 :UTURN,:SUBSTITUTE,:SNARL,:DARKPULSE,:CONFIDE,
                 :ROAR,:BULKUP,:VENOSHOCK,:SUNNYDAY,:HYPERBEAM,
                 :SLUDGEWAVE,:GIGAIMPACT,:SWORDSDANCE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:RAICHU,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:PSYCHIC) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 0.7 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 21.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:SURGESURFER),0],
                    [getID(PBAbilities,:SURGESURFER),2]]
      end
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [60,85,50,110,95,85] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[]
       movelist=[[1,:PSYCHIC],[1,:SPEEDSWAP],[1,:THUNDERSHOCK],
                 [1,:TAILWHIP],[1,:QUICKATTACK],[1,:THUNDERBOLT]]
       for i in movelist
         i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :PSYSHOCK,:CALMMIND,:TOXIC,:HIDDENPOWER,:HYPERBEAM,
                 :LIGHTSCREEN,:PROTECT,:RAINDANCE,:SAFEGUARD,:FRUSTRATION,
                 :THUNDERBOLT,:THUNDER,:RETURN,:PSYCHIC,:BRICKBREAK,
                 :DOUBLETEAM,:REFLECT,:FACADE,:REST,:ATTRACT,
                 :THIEF,:ROUND,:ECHOEDVOICE,:FOCUSBLAST,:FLING,
                 :CHARGEBEAM,:GIGAIMPACT,:VOLTSWITCH,:THUNDERWAVE,
                 :GRASSKNOT,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,
                 :WILDCHARGE,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:SANDSHREW,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:ICE) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:STEEL) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 0.6 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 40.0 if pokemon.isDelta?
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [50,75,90,40,10,35] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:SCRATCH],[1,:DEFENSECURL],[3,:BIDE],[5,:PODERSNOW],
                  [7,:ICEBALL],[9,:RAPIDSPIN],[11,:FURYCUTTER],[14,:METALCLAW],
                  [17,:SWIFT],[20,:FURYSWIPES],[23,:IRONDEFENSE],[26,:SLASH],
                  [30,:IRONHEAD],[34,:GYROBALL],[38,:SWORDSDANCE],[42,:HAIL],
                  [46,:BLIZZARD]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HAIL,:HIDDENPOWER,:SUNNYDAY,
                 :BLIZZARD,:PROTECT,:SAFEGUARD,:FRUSTRATION,:EARTHQUAKE,
                 :RETURN,:LEECHLIFE,:BRICKBREAK,:DOUBLETEAM,:AERIALACE,
                 :FACADE,:REST,:ATTRACT,:THIEF,:ROUND,
                 :FLING,:SHADOWCLAW,:AURORAVEIL,:GYROBALL,:SWORDSDANCE,
                 :BULLDOZE,:FROSTBREATH,:ROCKSLIDE,:XSCISSOR,
                 :POISONJAB,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,
                 :CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:AMNESIA,:CHIPAWAY,:COUNTER,:CRUSHCLAW,:CURSE,
                 :ENDURE,:FLAIL,:ICICLECRASH,:ICICLESPEAR,:METALCLAW,
                 :NIGHTSLASH]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:SNOWCLOAK),0]] if getID(PBAbilities,:SLUSHRUSH)==nil
        next [[getID(PBAbilities,:SNOWCLOAK),0],
              [getID(PBAbilities,:SLUSHRUSH),2]]
      end
      next
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:SANDSLASH,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:ICE) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:STEEL) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 1.2 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 55.0 if pokemon.isDelta?
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [75,100,120,65,25,65] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:ICICLESPEAR],[1,:METALBURST],[1,:ICICLECRASH],[1,:SLASH],
                  [1,:DEFENSECURL],[1,:ICEBALL],[1,:METALCLAW]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HAIL,:HIDDENPOWER,:SUNNYDAY,
                 :BLIZZARD,:PROTECT,:SAFEGUARD,:FRUSTRATION,:EARTHQUAKE,
                 :RETURN,:LEECHLIFE,:BRICKBREAK,:DOUBLETEAM,:AERIALACE,
                 :FACADE,:REST,:ATTRACT,:THIEF,:ROUND,
                 :FLING,:SHADOWCLAW,:AURORAVEIL,:GYROBALL,:SWORDSDANCE,
                 :BULLDOZE,:FROSTBREATH,:ROCKSLIDE,:XSCISSOR,
                 :POISONJAB,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,
                 :CONFIDE,:HYPERBEAM,:FOCUSBLAST,:GIGAIMPACT]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:SNOWCLOAK),0]] if getID(PBAbilities,:SLUSHRUSH)==nil
        next [[getID(PBAbilities,:SNOWCLOAK),0],
              [getID(PBAbilities,:SLUSHRUSH),2]]
      end
      next
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:VULPIX,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:ICE) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:ICE) if pokemon.isDelta?
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:POWDERSNOW],[4,:TAILWHIP],[7,:ROAR],[9,:BABYDOLLEYES],
                  [10,:ICESHARD],[12,:CONFUSERAY],[15,:ICYWIND],
                  [18,:PAYBACK],[20,:MIST],[23,:FEINTATTACK],[26,:HEX],
                  [28,:AURORABEAM],[31,:EXTRASENSORY],[34,:SAFEGUARD],
                  [36,:ICEBEAM],[39,:IMPRISON],[42,:BLIZZARD],[44,:GRUDGE],
                  [47,:CAPTIVATE],[50,:SHEERCOLD]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :ROAR,:TOXIC,:HAIL,:HIDDENPOWER,:ICEBEAM,
                 :BLIZZARD,:PROTECT,:RAINDANCE,:SAFEGUARD,:FRUSTRATION,
                 :RETURN,:DOUBLETEAM,:FACADE,:REST,:ATTRACT,:ROUND,
                 :PAYBACK,:AURORAVEIL,:PSYCHUP,:FROSTBREATH,
                 :SWAGGER,:SLEEPTALK,:SUBSTITUTE,
                 :CONFIDE,:DARKPULSE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:AGILITY,:CHARM,:DISABLE,:ENCORE,:EXTRASENSORY,
                 :FLAIL,:FREEZEDRY,:HOWL,:HYPNOSIS,:MOONBLAST,
                 :POWERSWAP,:SPITE,:SECRETPOWER,:TAILSLAP]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:SNOWCLOAK),0],
              [getID(PBAbilities,:SNOWWARNING),2]]
      end
      next
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:NINETAILS,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:ICE) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:FAIRY) if pokemon.isDelta?
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [73,67,75,109,81,100] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:DAZZLINGGLEAM],[1,:IMPRISON],[1,:NASTYPLOT],[1,:ICEBEAM],
                  [1,:ICESHARD],[1,:CONFUSERAY],[1,:SAFEGUARD]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :ROAR,:TOXIC,:HAIL,:HIDDENPOWER,:ICEBEAM,
                 :BLIZZARD,:PROTECT,:RAINDANCE,:SAFEGUARD,:FRUSTRATION,
                 :RETURN,:DOUBLETEAM,:FACADE,:REST,:ATTRACT,:ROUND,
                 :PAYBACK,:AURORAVEIL,:PSYCHUP,:FROSTBREATH,
                 :SWAGGER,:SLEEPTALK,:SUBSTITUTE,:CONFIDE,:DARKPULSE,
                 :PSYSHOCK,:CALMMIND,:GIGAIMPACT,:DREAMEATER,:DAZZLINGGLEAM]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:SNOWCLOAK),0],
              [getID(PBAbilities,:SNOWWARNING),2]]
      end
      next
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:DIGLETT,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:STEEL) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 1.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:TANGLINGHAIR)==nil
          next [[getID(PBAbilities,:SANDVEIL),0],
                [getID(PBAbilities,:GOOEY),1],
                [getID(PBAbilities,:SANDFORCE),2]]
        end
        next [[getID(PBAbilities,:SANDVEIL),0],
              [getID(PBAbilities,:TANGLEDHAIR),1],
              [getID(PBAbilities,:SANDFORCE),2]]
      end
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [10,55,30,90,35,45] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:SANDATTACK],[1,:METALCLAW],[4,:GROWL],[7,:ASTONISH],
                  [10,:MUDSLAP],[14,:MAGNITUDE],[18,:BULLDOZE],
                  [22,:SUCKERPUNCH],[25,:MUDBOMB],[28,:EARTHPOWER],[31,:DIG],
                  [35,:IRONHEAD],[39,:EARTHQUAKE],[43,:FISSURE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HIDDENPOWER,:SUNNYDAY,:PROTECT,
                 :FRUSTRATION,:EARTHQUAKE,:RETURN,:DOUBLETEAM,
                 :SLUDGEBOMB,:SANDSTORM,:ROCKTOMB,:AERIELACE,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:ECHOEDVOICE,
                 :SHADOWCLAW,:BULLDOZE,:ROCKSLIDE,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:FLASHCANNON,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:ANCIENTPOWER,:BEATUP,:ENDURE,:FEINTATTACK,
                 :FINALGAMBIT,:HEADBUTT,:MEMENTO,:METALSOUND,
                 :PURSUIT,:REVERSAL,:THRASH]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:DUGTRIO,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:STEEL) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 66.6 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:TANGLINGHAIR)==nil
          next [[getID(PBAbilities,:SANDVEIL),0],
                [getID(PBAbilities,:GOOEY),1],
                [getID(PBAbilities,:SANDFORCE),2]]
        end
        next [[getID(PBAbilities,:SANDVEIL),0],
              [getID(PBAbilities,:TANGLEDHAIR),1],
              [getID(PBAbilities,:SANDFORCE),2]]
      end
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [35,100,60,110,50,70] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:SANDTOMB],[1,:ROTOTILLER],[1,:NIGHTSLASH],
                  [1,:TRIATTACK],[1,:SANDATTACK],[1,:METALCLAW],
                  [1,:GROWL],[4,:GROWL],[7,:ASTONISH],
                  [10,:MUDSLAP],[14,:MAGNITUDE],[18,:BULLDOZE],
                  [22,:SUCKERPUNCH],[25,:MUDBOMB],[30,:EARTHPOWER],[35,:DIG],
                  [41,:IRONHEAD],[47,:EARTHQUAKE],[53,:FISSURE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HIDDENPOWER,:SUNNYDAY,:PROTECT,
                 :FRUSTRATION,:EARTHQUAKE,:RETURN,:DOUBLETEAM,
                 :SLUDGEBOMB,:SANDSTORM,:ROCKTOMB,:AERIELACE,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:ECHOEDVOICE,
                 :SHADOWCLAW,:BULLDOZE,:ROCKSLIDE,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:FLASHCANNON,:CONFIDE,:HYPERBEAM,
                 :SLUDGEWAVE,:GIGAIMPACT,:STONEEDGE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:MEOWTH,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:PICKUP),0],
              [getID(PBAbilities,:TECHNICIAN),1],
              [getID(PBAbilities,:RATTLED),2]]
      end
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [40,35,34,90,50,40] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:SCRATCH],[1,:GROWL],[6,:BITE],[9,:FAKEOUT],
                  [14,:FURYSWIPES],[17,:SCREECH],[22,:FEINTATTACK],
                  [25,:TAUNT],[30,:PAYDAY],[33,:SLASH],[38,:NASTYPLOT],
                  [41,:ASSURANCE],[46,:CAPTIVATE],[49,:NIGHTSLASH],
                  [50,:FEINT],[55,:DARKPULSE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HIDDENPOWER,:SUNNYDAY,:TAUNT,:PROTECT,
                 :RAINDANCE,:FRUSTRATION,:THUNDERBOLT,:THUNDER,:RETURN,
                 :SHADOWBALL,:DOUBLETEAM,:AERIELACE,:TORMENT,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:ECHOEDVOICE,:QUASH,
                 :EMBARGO,:SHADOWCLAW,:PAYBACK,:PSYCHUP,:DREAMEATER,
                 :SWAGGER,:SLEEPTALK,:UTURN,:SUBSTITUTE,:DARKPULSE,
                 :CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:AMNESIA,:ASSIST,:CHARM,:COVET,:FLAIL,:FLATTER,
                 :FOULPLAY,:HYPNOSIS,:PARTINGSHOT,:PUNISHMENT,
                 :SNATCH,:SPITE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:PERSIAN,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 1.1 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 33.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:FURCOAT),0],
              [getID(PBAbilities,:TECHNICIAN),1],
              [getID(PBAbilities,:RATTLED),2]]
      end
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [65,60,60,115,75,65] if pokemon.isDelta?
       next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:SWIFT],[1,:QUASH],[1,:PLAYROUGH],[1,:SWITCHEROO],
                  [1,:SCRATCH],[1,:GROWL],[1,:BITE],[1,:FAKEOUT],
                  [6,:BITE],[9,:FAKEOUT],[14,:FURYSWIPES],[17,:SCREECH],
                  [22,:FEINTATTACK],[25,:TAUNT],[32,:POWERGEM],[37,:SLASH],
                  [44,:NASTYPLOT],[49,:ASSURANCE],[56,:CAPTIVATE],
                  [61,:NIGHTSLASH],[65,:FEINT],[69,:DARKPULSE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :WORKUP,:TOXIC,:HIDDENPOWER,:SUNNYDAY,:TAUNT,:PROTECT,
                 :RAINDANCE,:FRUSTRATION,:THUNDERBOLT,:THUNDER,:RETURN,
                 :SHADOWBALL,:DOUBLETEAM,:AERIELACE,:TORMENT,:FACADE,
                 :REST,:ATTRACT,:THIEF,:ROUND,:ECHOEDVOICE,:QUASH,
                 :EMBARGO,:SHADOWCLAW,:PAYBACK,:PSYCHUP,:DREAMEATER,
                 :SWAGGER,:SLEEPTALK,:UTURN,:SUBSTITUTE,:DARKPULSE,
                 :CONFIDE,:ROAR,:HYPERBEAM,:GIGAIMPACT,:SNARL]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:GEODUDE,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:ELECTRIC) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 20.3 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:GALVANIZE)==nil
          next [[getID(PBAbilities,:MAGNETPULL),0],
                [getID(PBAbilities,:STURDY),1]]
        end
        next [[getID(PBAbilities,:MAGNETPULL),0],
              [getID(PBAbilities,:STURDY),1],
              [getID(PBAbilities,:GALVANIZE),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:TACKLE],[1,:DEFENSECURL],[4,:CHARGE],[6,:ROCKPOLISH],
                  [10,:ROLLOUT],[12,:SPARK],[16,:ROCKTHROW],[18,:SMACKDOWN],
                  [22,:THUNDERPUNCH],[24,:SELFDESTRUCT],[28,:STEALTHROCK],
                  [30,:ROCKBLAST],[34,:DISCHARGE],[36,:EXPLOSION],
                  [40,:DOUBLEEDGE],[42,:STONEEDGE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:PROTECT,:SMACKDOWN,
                 :THUNDERBOLT,:THUNDER,:EARTHQUAKE,:RETURN,:BRICKBREAK,
                 :DOUBLETEAM,:FLAMETHROWER,:SANDSTORM,:FIREBLAST,
                 :ROCKTOMB,:FACADE,:REST,:ATTRACT,:ROUND,
                 :FLING,:CHARGEBEAM,:BRUTALSWING,:EXPLOSION,
                 :ROCKPOLISH,:STONEEDGE,:VOLTSWITCH,:GYROBALL,
                 :BULLDOZE,:ROCKSLIDE,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:NATUREPOWER,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:AUTOTOMIZE,:BLOCK,:COUNTER,:CURSE,:ENDURE,:FLAIL,
                 :MAGNETRISE,:ROCKCLIMB,:SCREECH,:WIDEGUARD]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:GRAVELER,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:ELECTRIC) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 110.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:GALVANIZE)==nil
          next [[getID(PBAbilities,:MAGNETPULL),0],
                [getID(PBAbilities,:STURDY),1]]
        end
        next [[getID(PBAbilities,:MAGNETPULL),0],
              [getID(PBAbilities,:STURDY),1],
              [getID(PBAbilities,:GALVANIZE),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:TACKLE],[1,:DEFENSECURL],[1,:CHARGE],[1,:ROCKPOLISH],
                  [4,:CHARGE],[6,:ROCKPOLISH],[10,:ROLLOUT],[12,:SPARK],
                  [16,:ROCKTHROW],[18,:SMACKDOWN],[22,:THUNDERPUNCH],
                  [24,:SELFDESTRUCT],[30,:STEALTHROCK],[34,:ROCKBLAST],
                  [40,:DISCHARGE],[44,:EXPLOSION],[50,:DOUBLEEDGE],
                  [54,:STONEEDGE]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:PROTECT,:SMACKDOWN,
                 :THUNDERBOLT,:THUNDER,:EARTHQUAKE,:RETURN,:BRICKBREAK,
                 :DOUBLETEAM,:FLAMETHROWER,:SANDSTORM,:FIREBLAST,
                 :ROCKTOMB,:FACADE,:REST,:ATTRACT,:ROUND,
                 :FLING,:CHARGEBEAM,:BRUTALSWING,:EXPLOSION,
                 :ROCKPOLISH,:STONEEDGE,:VOLTSWITCH,:GYROBALL,
                 :BULLDOZE,:ROCKSLIDE,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:NATUREPOWER,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:GOLEM,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:ELECTRIC) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 110.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:GALVANIZE)==nil
          next [[getID(PBAbilities,:MAGNETPULL),0],
                [getID(PBAbilities,:STURDY),1]]
        end
        next [[getID(PBAbilities,:MAGNETPULL),0],
              [getID(PBAbilities,:STURDY),1],
              [getID(PBAbilities,:GALVANIZE),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:HEAVYSLAM],[1,:TACKLE],[1,:DEFENSECURL],[1,:CHARGE],
                  [1,:ROCKPOLISH],[4,:CHARGE],[6,:ROCKPOLISH],
                  [10,:STEAMROLLER],[12,:SPARK],[16,:ROCKTHROW],
                  [18,:SMACKDOWN],[22,:THUNDERPUNCH],[24,:SELFDESTRUCT],
                  [30,:STEALTHROCK],[34,:ROCKBLAST],[40,:DISCHARGE],
                  [44,:EXPLOSION],[50,:DOUBLEEDGE],[54,:STONEEDGE],
                  [60,:HEAVYSLAM]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:PROTECT,:SMACKDOWN,
                 :THUNDERBOLT,:THUNDER,:EARTHQUAKE,:RETURN,:BRICKBREAK,
                 :DOUBLETEAM,:FLAMETHROWER,:SANDSTORM,:FIREBLAST,
                 :ROCKTOMB,:FACADE,:REST,:ATTRACT,:ROUND,
                 :FLING,:CHARGEBEAM,:BRUTALSWING,:EXPLOSION,
                 :ROCKPOLISH,:STONEEDGE,:VOLTSWITCH,:GYROBALL,
                 :BULLDOZE,:ROCKSLIDE,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:NATUREPOWER,:CONFIDE,:ROAR,:HYPERBEAM,
                 :FRUSTRATION,:ECHOEDVOICE,:FOCUSBLAST,:GIGAIMPACT,
                 :WILDCHARGE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:GRIMER,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 0.7 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 42.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:POWEROFALCHEMY)==nil
          if getID(PBAbilities,:RECEIVER)==nil
            next [[getID(PBAbilities,:POISONTOUCH),0],
                  [getID(PBAbilities,:GLUTTONY),1]]
          end
          next [[getID(PBAbilities,:POISONTOUCH),0],
                [getID(PBAbilities,:GLUTTONY),1],
                [getID(PBAbilities,:RECEIVER),2]]
        end
        next [[getID(PBAbilities,:POISONTOUCH),0],
              [getID(PBAbilities,:GLUTTONY),1],
              [getID(PBAbilities,:POWEROFALCHEMY),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:POUND],[1,:POISONGAS],[4,:HARDEN],[7,:BITE],[12,:DISABLE],
                  [15,:ACIDSPRAY],[18,:POISONFANG],[21,:MINIMIZE],[26,:FLING],
                  [29,:KNOCKOFF],[32,:CRUNCH],[37,:SCREECH],[40,:GUNKSHOT],
                  [43,:ACIDARMOR],[46,:BELCH],[48,:MEMENTO]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:VENOSHOCK,:HIDDENPOWER,:SUNNYDAY,:TAUNT,
                 :PROTECT,:RAINDANCE,:FRUSTRATION,:RETURN,:SHADOWBALL,
                 :DOUBLETEAM,:SLUDGEWAVE,:FLAMETHROWER,:SLUDGEBOMB,
                 :FIREBLAST,:ROCKTOMB,:TORMENT,:FACADE,:REST,:ATTRACT,
                 :THIEF,:ROUND,:FLING,:BRUTALSWING,:QUASH,:EMBARGO,
                 :EXPLOSION,:PAYBACK,:ROCKPOLISH,:STONEEDGE,:INFESTATION,
                 :POISONJAB,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,:SNARL,:CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "possibleEggMoves"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[:ASSURANCE,:CLEARSMOG,:CURSE,:IMPRISION,:MEANLOOK,:PURSUIT,
                 :SCARYFACE,:SHADOWSNEAK,:SPITE,:STOCKPILE,:SPITUP,:SWALLOW]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:MUK,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:DARK) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 1.0 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 52.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        if getID(PBAbilities,:POWEROFALCHEMY)==nil
          if getID(PBAbilities,:RECEIVER)==nil
            next [[getID(PBAbilities,:POISONTOUCH),0],
                  [getID(PBAbilities,:GLUTTONY),1]]
          end
          next [[getID(PBAbilities,:POISONTOUCH),0],
                [getID(PBAbilities,:GLUTTONY),1],
                [getID(PBAbilities,:RECEIVER),2]]
        end
        next [[getID(PBAbilities,:POISONTOUCH),0],
              [getID(PBAbilities,:GLUTTONY),1],
              [getID(PBAbilities,:POWEROFALCHEMY),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:VENOMDRENCH],[1,:POUND],[1,:POISONGAS],[1,:HARDEN],
                  [1,:BITE],[4,:HARDEN],[7,:BITE],[12,:DISABLE],
                  [15,:ACIDSPRAY],[18,:POISONFANG],[21,:MINIMIZE],[26,:FLING],
                  [29,:KNOCKOFF],[32,:CRUNCH],[37,:SCREECH],[40,:GUNKSHOT],
                  [46,:ACIDARMOR],[52,:BELCH],[57,:MEMENTO]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1]) if getConst(PBMoves,movelist[i])!=nil
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:VENOSHOCK,:HIDDENPOWER,:SUNNYDAY,:TAUNT,
                 :PROTECT,:RAINDANCE,:FRUSTRATION,:RETURN,:SHADOWBALL,
                 :DOUBLETEAM,:SLUDGEWAVE,:FLAMETHROWER,:SLUDGEBOMB,
                 :FIREBLAST,:ROCKTOMB,:TORMENT,:FACADE,:REST,:ATTRACT,
                 :THIEF,:ROUND,:FLING,:BRUTALSWING,:QUASH,:EMBARGO,
                 :EXPLOSION,:PAYBACK,:ROCKPOLISH,:STONEEDGE,:INFESTATION,
                 :POISONJAB,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,:SNARL,
                 :CONFIDE,:HYPERBEAM,:BRICKBREAK,:FOCUSBLAST,
                 :GIGAIMPACT,:DARKPULSE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:EXEGGUTOR,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:DRAGON) if pokemon.isDelta?
      next
    },
    "height"=>proc{|pokemon|
      next 10.9 if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 415.6 if pokemon.isDelta?
      next
    },
    "getBaseStats"=>proc{|pokemon|
       next [95,105,85,45,125,75] if pokemon.isDelta?
       next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:FRISK),0],
              [getID(PBAbilities,:HARVEST),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:DRAGONHAMMER],[1,:SEEDBOMB],[1,:BARRAGE],[1,:HYPNOSIS],
                  [1,:CONFUSION],[17,:PSYSHOCK],[27,:EGGBOMB],[37,:WOODHAMMER],
                  [47,:LEAFSTORM]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1])
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :PSYSHOCK,:TOXIC,:HIDDENPOWER,:SUNNYDAY,:HYPERBEAM,
                 :LIGHTSCREEN,:PROTECT,:FRUSTRATION,:SOLARBEAM,:EARTHQUAKE,
                 :RETURN,:PSYCHIC,:BRICKBREAK,:DOUBLETEAM,:REFLECT,
                 :FLAMETHROWER,:SLUDGEBOMB,:FACADE,:REST,:ATTRACT,
                 :THIEF,:ROUND,:ENERGYBALL,:BRUTALSWING,:EXPLOSION,
                 :GIGAIMPACT,:SWORDSDANCE,:PSYCHUP,:BULLDOZE,:DRAGONTAIL,
                 :INFESTATION,:DREAMEATER,:GRASSKNOT,:SWAGGER,:SLEEPTALK,
                 :SUBSTITUTE,:TRICKEROOM,:NATUREPOWER,:CONFIDE,:DRACOMETEOR]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    MultipleForms.register(:MAROWAK,{
    "getFormName"=>proc{|pokemon|
      next _INTL("Alola Form") if pokemon.isDelta?
      next
    },
    "type1"=>proc{|pokemon|
      next getID(PBTypes,:FIRE) if pokemon.isDelta?
      next
    },
    "type2"=>proc{|pokemon|
      next getID(PBTypes,:GHOST) if pokemon.isDelta?
      next
    },
    "weight"=>proc{|pokemon|
      next 34.0 if pokemon.isDelta?
      next
    },
    "getAbilityList"=>proc{|pokemon|
      if pokemon.isDelta?
        next [[getID(PBAbilities,:CURSEDBODY),0],
              [getID(PBAbilities,:LIGHTNINGROD),1],
              [getID(PBAbilities,:ROCKHEAD),2]]
      end
      next
    },
    "getMoveList"=>proc{|pokemon|
      next if !pokemon.isDelta?
      movelist=[]
      if pokemon.isDelta?
        movelist=[[1,:GROWL],[1,:TAILWHIP],[1,:BONECLUB],[1,:FLAMEWHEEL],
                  [3,:TAILWHIP],[7,:BONECLUB],[11,:FLAMEWHEEL],[13,:LEER],
                  [17,:HEX],[21,:BONEMERANG],[23,:WILLOWISP],[27,:SHADOWBONE],
                  [33,:THRASH],[37,:FLING],[43,:STOMPINGTANTRUM],[49,:ENDEAVOR],
                  [53,:FLAREBLITZ],[59,:RETALIATE],[65,:BONERUSH]]
      end
      for i in movelist
        i[1]=getConst(PBMoves,i[1])
      end
      next movelist
    },
    "getMoveCompatibility"=>proc{|pokemon|
       next if !pokemon.isDelta?
       movelist=[# TMs
                 :TOXIC,:HIDDENPOWER,:SUNNYDAY,:ICEBEAM,:BLIZZARD,:HYPERBEAM,
                 :PROTECT,:RAINDANCE,:FRUSTRATION,:SMACKDOWN,:THUNDERBOLT,
                 :THUNDER,:EARTHQUAKE,:RETURN,:SHADOWBALL,:BRICKBREAK,:DOUBLETEAM,
                 :FLAMETHROWER,:SANDSTORM,:FIREBLAST,:ROCKTOMB,:AERIALACE,:FACADE,
                 :FLAMECHARGE,:REST,:ATTRACT,:THIEF,:ROUND,:ECHOEDVOICE,
                 :FOCUSBLAST,:FALSESWIPE,:FLING,:BRUTALSWING,:WILLOWISP,
                 :GIGAIMPACT,:STONEEDGE,:SWORDSDANCE,:BULLDOZE,:ROCKSLIDE,
                 :DREAMEATER,:SWAGGER,:SLEEPTALK,:SUBSTITUTE,:DARKPULSE,
                 :CONFIDE]
       for i in 0...movelist.length
         movelist[i]=getConst(PBMoves,movelist[i]) if getConst(PBMoves,movelist[i])!=nil
       end
       next movelist
    },
    "onSetForm"=>proc{|pokemon,form|
      pbSeenForm(pokemon)
    }
    })
    
    ###################################################################
    # EXAMPLE ENCOUNTER MODIFIER
    # This makes Exeggutor that are created on a particular map
    #    become Alolan Exeggutor automatically.
    # Evolving Exeggcute on this map will not make them become Alolan
    #    Exeggutor.  Only wild Exeggutor.
    # "pokemon.makeDelta" is how to make the Pokemon a Delta/Alolan
    ###################################################################
    # Events.onWildPokemonCreate+=proc {|sender,e|
    #    pokemon=e[0]
    #    if $game_map.map_id==51 && isConst?(pokemon.species,PBSpecies,:EXEGGUTOR)
    #      pokemon.makeDelta
    #    end
    # }
    
    ###################################################################
    # EXAMPLE RANDOM SPAWNER MODIFIER
    # This makes Delta/Alolan Pokemon spawn randomly, at the same rate
    #    as Shiny Pokemon do
    # Note that this method doesn't allow for Shiny Delta/Alolan
    #    Pokemon, as the possible numbers for it don't overlap.
    # Note also that this does not make a Delta for every species.
    #    If a species doesn't have a Delta/Alolan Form defined, than
    #    this function is meaningless.
    ###################################################################
    # class PokeBattle_Pokemon
    #   def isDelta?
    #     return @deltaflag if @deltaflag!=nil
    #     [email protected]^@trainerID
    #     b=a&0xFFFF
    #     c=(a>>16)&0xFFFF
    #     d=b^c
    #     return (d>65536-SHINYPOKEMONCHANCE)
    #   end
    # end
    In order to make a sprite for an Alolan Pokemon, name the sprite "###d.png", where the ### is replaced with the National Pokedex number of the species. For example, Alolan Ninetales's sprite would be named "038d.png". This can be combined with the existing modifiers - "###sd.png" for a Shiny Alolan Pokemon, "###db.png" for the backsprite of an Alolan Pokemon, "##fd.png" for a female Alolan Pokemon, "###d_1.png" for the (numbered) alternate form of an Alolan Pokemon, etc. (In order to do the backsprite for a female Shiny Alolan Pokemon in a numbered alternate form, the proper syntax is "###fsdb_1.png")
    __________________
    Features of Pokemon Entropy

    The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
    Reply With Quote
      #2    
    Old August 4th, 2016 (12:08 AM).
    didcjfdndz didcjfdndz is offline
       
      Join Date: Nov 2013
      Location: Korean
      Gender: Male
      Nature: Jolly
      Posts: 2
      I Think this script very awesome!
      Reply With Quote
        #3    
      Old August 4th, 2016 (8:20 AM).
      Rot8er_ConeX's Avatar
      Rot8er_ConeX Rot8er_ConeX is offline
         
        Join Date: May 2015
        Location: The Dissa Region
        Gender: Male
        Posts: 822
        Quote:
        Originally Posted by didcjfdndz View Post
        I Think this script very awesome!
        It's a very dumbed down version of the way Delta Pokemon work in my game, (dumbed down because I needed to make it plug-and-play). I've previously avoided telling anyone what code changes I made, but now that it appears that Game Freak is going down the same path I did, there's no longer the excuse of "wanting to keep this feature unique to my own game".
        __________________
        Features of Pokemon Entropy

        The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
        Reply With Quote
          #4    
        Old August 4th, 2016 (9:07 PM).
        Sir_Tman's Avatar
        Sir_Tman Sir_Tman is offline
        Head Developer of Pokemon Elemento
           
          Join Date: Aug 2015
          Location: Evergreen City - Elemento Region
          Gender: Male
          Nature: Relaxed
          Posts: 189
          Dear lord we only just got Alola Forms announced the other day. So how would this work for mega evolutions? Do we need to add a line in to check if its Alola Form?
          __________________
          Reply With Quote
            #5    
          Old August 4th, 2016 (9:16 PM).
          Rot8er_ConeX's Avatar
          Rot8er_ConeX Rot8er_ConeX is offline
             
            Join Date: May 2015
            Location: The Dissa Region
            Gender: Male
            Posts: 822
            Quote:
            Originally Posted by Sir_Tman View Post
            Dear lord we only just got Alola Forms announced the other day
            This is a variation of code I was already using in my own game for over a year now. Game Freak's reveal of Alola Forms just prompted me to go public with it.

            Quote:
            So how would this work for mega evolutions? Do we need to add a line in to check if its Alola Form?
            Well, at the moment we don't have any Alolan Forms that can Mega Evolve, so we don't know if they'll have their own Mega Stones or use the basic ones for their species.

            But, in my own game, Steelix has a Mega form and a Delta form, and the Delta form has a different Mega from the non-Delta. Here's my code for Steelix, so you can see how I did it.

            Code:
            MultipleForms.register(:STEELIX,{
            "getMegaForm"=>proc{|pokemon|
               next 1 if isConst?(pokemon.item,PBItems,:STEELIXITE)
               next
            },
            "getUnmegaForm"=>proc{|pokemon|
               next 0
            },
            "getMegaName"=>proc{|pokemon|
               next _INTL("Mega Steelix") if pokemon.form==1
               next
            },
            "getBaseStats"=>proc{|pokemon|
               next [75,135,225,55,65,55] if pokemon.form==1 && pokemon.isDelta?
               next [75,125,230,30,55,95] if pokemon.form==1
               next
            },
            "type1"=>proc{|pokemon|
               next getID(PBTypes,:FIRE) if pokemon.form==1 && pokemon.isDelta?
               next
            },
            "ability"=>proc{|pokemon|
               next getID(PBAbilities,:FOUNDRY) if pokemon.form==1 && pokemon.isDelta?
               next getID(PBAbilities,:SANDFORCE) if pokemon.form==1
               next
            },
            "height"=>proc{|pokemon|
               next 105 if pokemon.form==1
               next
            },
            "weight"=>proc{|pokemon|
               next 740.0 if pokemon.form==1
               next
            },
            "onSetForm"=>proc{|pokemon,form|
               pbSeenForm(pokemon)
            }
            })
            __________________
            Features of Pokemon Entropy

            The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
            Reply With Quote
              #6    
            Old August 5th, 2016 (7:57 PM).
            Rot8er_ConeX's Avatar
            Rot8er_ConeX Rot8er_ConeX is offline
               
              Join Date: May 2015
              Location: The Dissa Region
              Gender: Male
              Posts: 822
              Update to allow icons (on the Party screen and the PC) to change based on whether a Pokemon is Alolan or not. Naming the files follows similar rules to the battlers.
              __________________
              Features of Pokemon Entropy

              The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
              Reply With Quote
                #7    
              Old August 7th, 2016 (1:59 AM).
              Arkadious's Avatar
              Arkadious Arkadious is offline
              Developer of Fragmentum
                 
                Join Date: Nov 2015
                Location: New Zealand
                Age: 21
                Gender: Male
                Nature: Careful
                Posts: 50
                I'm getting this error with the latest update:

                Spoiler:
                Exception: ArgumentError
                Message: wrong number of arguments(3 for 2)
                Rot8er_ConeX Delta/Alolan Forms:205:in `pbCheckPokemonIconFiles'
                Rot8er_ConeX Delta/Alolan Forms:205:in `pbPokemonIconFile'
                Pokemon_Sprites:188:in `pokemon='
                Pokemon_Sprites:174:in `initialize'
                PScreen_Load:172:in `new'
                PScreen_Load:172:in `pbSetParty'
                PScreen_Load:171:in `each'
                PScreen_Load:171:in `pbSetParty'
                PScreen_Load:324:in `pbStartLoadScreen'
                Main:6:in `main'
                Reply With Quote
                  #8    
                Old August 7th, 2016 (12:48 PM).
                Rot8er_ConeX's Avatar
                Rot8er_ConeX Rot8er_ConeX is offline
                   
                  Join Date: May 2015
                  Location: The Dissa Region
                  Gender: Male
                  Posts: 822
                  Quote:
                  Originally Posted by Arkadious View Post
                  I'm getting this error with the latest update:

                  Spoiler:
                  Exception: ArgumentError
                  Message: wrong number of arguments(3 for 2)
                  Rot8er_ConeX Delta/Alolan Forms:205:in `pbCheckPokemonIconFiles'
                  Rot8er_ConeX Delta/Alolan Forms:205:in `pbPokemonIconFile'
                  Pokemon_Sprites:188:in `pokemon='
                  Pokemon_Sprites:174:in `initialize'
                  PScreen_Load:172:in `new'
                  PScreen_Load:172:in `pbSetParty'
                  PScreen_Load:171:in `each'
                  PScreen_Load:171:in `pbSetParty'
                  PScreen_Load:324:in `pbStartLoadScreen'
                  Main:6:in `main'
                  OOOOOPS, put a line in the wrong spot.

                  Thank you for catching that. Fix is now in the main post
                  __________________
                  Features of Pokemon Entropy

                  The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                  Reply With Quote
                    #9    
                  Old August 9th, 2016 (4:26 PM).
                  Dimbus Maximus's Avatar
                  Dimbus Maximus Dimbus Maximus is offline
                     
                    Join Date: Aug 2016
                    Location: AL, United States
                    Posts: 33
                    Nice work!
                    A neat thing a dev could do with this is check if the mother or father of an egg was an Alola/Deta pokémon and make a species-specific list of moves that could be passed down between the two subspecies.
                    __________________
                    Developer of Pokémon Meta Mercury
                    Reply With Quote
                      #10    
                    Old August 9th, 2016 (4:30 PM).
                    Rot8er_ConeX's Avatar
                    Rot8er_ConeX Rot8er_ConeX is offline
                       
                      Join Date: May 2015
                      Location: The Dissa Region
                      Gender: Male
                      Posts: 822
                      Edited the first post to include the new Delta/Alola Forms revealed in today's Corocoro
                      __________________
                      Features of Pokemon Entropy

                      The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                      Reply With Quote
                        #11    
                      Old August 11th, 2016 (4:26 PM).
                      Rot8er_ConeX's Avatar
                      Rot8er_ConeX Rot8er_ConeX is offline
                         
                        Join Date: May 2015
                        Location: The Dissa Region
                        Gender: Male
                        Posts: 822
                        Added the new information we learned about Alolan Meowth and Marowak in the trailer (their abilities), as well as Alolan Raichu entirely added.

                        Note that even though my code references the ability Surge Surfer, it doesn't add it. You need to do that yourself. The relevant bit of code is def pbSpeed(), which can be found on lines 642-701 of the script section PokeBattle_Battler.

                        Personally, I'd do it by inserting the red lines:
                        Code:
                          def pbSpeed()
                            stagemul=[10,10,10,10,10,10,10,15,20,25,30,35,40]
                            stagediv=[40,35,30,25,20,15,10,10,10,10,10,10,10]
                            [email protected]
                            [email protected][PBStats::SPEED]+6
                            speed=(speed*stagemul[stage]/stagediv[stage]).floor
                            speedmult=0x1000
                            case @battle.pbWeather
                            when PBWeather::RAINDANCE, PBWeather::HEAVYRAIN
                              speedmult=speedmult*2 if self.hasWorkingAbility(:SWIFTSWIM)
                            when PBWeather::SUNNYDAY, PBWeather::HARSHSUN
                              speedmult=speedmult*2 if self.hasWorkingAbility(:CHLOROPHYLL)
                            when PBWeather::SANDSTORM
                              speedmult=speedmult*2 if self.hasWorkingAbility(:SANDRUSH)
                            end
                            if self.hasWorkingAbility(:QUICKFEET) && self.status>0
                              speedmult=(speedmult*1.5).round
                            end
                            if self.hasWorkingAbility(:SURGESURFER) && @battle.field.effects[PBEffects::ElectricTerrain]>0
                              speedmult=speedmult*2
                            end
                            if self.hasWorkingAbility(:UNBURDEN) && @effects[PBEffects::Unburden] &&
                               self.item==0
                              speedmult=speedmult*2
                            end
                            if self.hasWorkingAbility(:SLOWSTART) && self.turncount<=5
                              speedmult=(speedmult/2).round
                            end
                            if self.hasWorkingItem(:MACHOBRACE) ||
                               self.hasWorkingItem(:POWERWEIGHT) ||
                               self.hasWorkingItem(:POWERBRACER) ||
                               self.hasWorkingItem(:POWERBELT) ||
                               self.hasWorkingItem(:POWERANKLET) ||
                               self.hasWorkingItem(:POWERLENS) ||
                               self.hasWorkingItem(:POWERBAND)
                              speedmult=(speedmult/2).round
                            end
                            if self.hasWorkingItem(:CHOICESCARF)
                              speedmult=(speedmult*1.5).round
                            end
                            if isConst?(self.item,PBItems,:IRONBALL)
                              speedmult=(speedmult/2).round
                            end
                            if self.hasWorkingItem(:QUICKPOWDER) && isConst?(self.species,PBSpecies,:DITTO) &&
                               [email protected][PBEffects::Transform]
                              speedmult=speedmult*2
                            end
                            if self.pbOwnSide.effects[PBEffects::Tailwind]>0
                              speedmult=speedmult*2
                            end
                            if self.pbOwnSide.effects[PBEffects::Swamp]>0
                              speedmult=(speedmult/2).round
                            end
                            if self.status==PBStatuses::PARALYSIS && !self.hasWorkingAbility(:QUICKFEET)
                              speedmult=(speedmult/4).round
                            end
                            if @battle.internalbattle && @battle.pbOwnedByPlayer?(@index) &&
                               @battle.pbPlayer.numbadges>=BADGESBOOSTSPEED
                              speedmult=(speedmult*1.1).round
                            end
                            speed=(speed*speedmult*1.0/0x1000).round
                            return [speed,1].max
                          end
                        __________________
                        Features of Pokemon Entropy

                        The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                        Reply With Quote
                          #12    
                        Old August 16th, 2016 (3:25 PM).
                        monyarm monyarm is offline
                           
                          Join Date: Dec 2008
                          Gender:
                          Posts: 6
                          Can you make it so it's possible to add more the 1 delta form per pokemon?
                          Reply With Quote
                            #13    
                          Old August 16th, 2016 (8:28 PM).
                          Rot8er_ConeX's Avatar
                          Rot8er_ConeX Rot8er_ConeX is offline
                             
                            Join Date: May 2015
                            Location: The Dissa Region
                            Gender: Male
                            Posts: 822
                            Quote:
                            Originally Posted by monyarm View Post
                            Can you make it so it's possible to add more the 1 delta form per pokemon?
                            This is designed to work like how the Gen VII games seem to do this. But you could use a combination of this and the default form code to make multiple deltas.
                            __________________
                            Features of Pokemon Entropy

                            The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                            Reply With Quote
                              #14    
                            Old August 19th, 2016 (7:31 AM).
                            monyarm monyarm is offline
                               
                              Join Date: Dec 2008
                              Gender:
                              Posts: 6
                              I'm getting a syntax error on line 207
                              Reply With Quote
                                #15    
                              Old August 19th, 2016 (8:44 AM).
                              Rot8er_ConeX's Avatar
                              Rot8er_ConeX Rot8er_ConeX is offline
                                 
                                Join Date: May 2015
                                Location: The Dissa Region
                                Gender: Male
                                Posts: 822
                                Quote:
                                Originally Posted by monyarm View Post
                                I'm getting a syntax error on line 207
                                Try removing the comma on that line.
                                __________________
                                Features of Pokemon Entropy

                                The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                                Reply With Quote
                                  #16    
                                Old August 21st, 2016 (2:18 PM). Edited August 21st, 2016 by victorcarvalhosp.
                                victorcarvalhosp victorcarvalhosp is offline
                                   
                                  Join Date: Aug 2016
                                  Gender: Male
                                  Posts: 1
                                  Great script!

                                  But I have some doubts:

                                  This script is compatible with EliteBattle? Because If i add it above EliteBattle scripts I got this error when entering any battle:



                                  If I put below I don't receive anu error, but the sprite of the Pokémon doens't change...
                                  Reply With Quote
                                    #17    
                                  Old August 21st, 2016 (5:54 PM).
                                  Rot8er_ConeX's Avatar
                                  Rot8er_ConeX Rot8er_ConeX is offline
                                     
                                    Join Date: May 2015
                                    Location: The Dissa Region
                                    Gender: Male
                                    Posts: 822
                                    Quote:
                                    Originally Posted by victorcarvalhosp View Post
                                    Great script!

                                    But I have some doubts:

                                    This script is compatible with EliteBattle? Because If i add it above EliteBattle scripts I got this error when entering any battle:



                                    If I put below I don't receive anu error, but the sprite of the Pokémon doens't change...
                                    If you're using the Elite Battle System, place this script below the EBS scripts. Both systems overwrite the same functions, and mine are based on the EBS's

                                    Did you make sprites for a the Delta forms? The code doesn't come with new sprites - you have to find/make them yourself.
                                    __________________
                                    Features of Pokemon Entropy

                                    The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                                    Reply With Quote
                                      #18    
                                    Old August 23rd, 2016 (7:28 AM).
                                    Marty152's Avatar
                                    Marty152 Marty152 is offline
                                       
                                      Join Date: May 2013
                                      Location: The Netherlands
                                      Gender: Male
                                      Posts: 16
                                      I've got the same error with the number of arguments of the bitmapwrapper, but in my project it appears in any battle when the delta species script is below the elite battle scripts. When it's above, I don't get any error, but also no appearance change. I've only made a sprite for the front just to check if it worked. Do you know what might cause this?
                                      __________________
                                      Reply With Quote
                                        #19    
                                      Old August 23rd, 2016 (3:21 PM).
                                      BlackOutG5's Avatar
                                      BlackOutG5 BlackOutG5 is offline
                                         
                                        Join Date: Jul 2015
                                        Gender: Male
                                        Nature: Bold
                                        Posts: 77
                                        Guys I fixed the error for people who has Elite Battlers and it still crashed I'll post on this link tomorrow the fix Because I'm tired after trying to fix this mess for ages.
                                        Reply With Quote
                                          #20    
                                        Old August 23rd, 2016 (7:16 PM). Edited August 23rd, 2016 by Rot8er_ConeX.
                                        Rot8er_ConeX's Avatar
                                        Rot8er_ConeX Rot8er_ConeX is offline
                                           
                                          Join Date: May 2015
                                          Location: The Dissa Region
                                          Gender: Male
                                          Posts: 822
                                          Okay, so I've figured out the problem in regards to the EBS. Working on a solution that doesn't mess with compatibility for non-EBS systems in the process of fixing it for the EBS.

                                          The issue has to do with the EBS being able to auto-scale sprites. It's looking for that scale parameter, and not finding it.


                                          EDIT: the first post has been edited to be compatible with the EBS. the function pbLoadPokemonBitmapSpecies( has been edited, and the function pbLoadPokemonBitmap( has been entirely added to take advantage of the new functionality in the edited function.
                                          __________________
                                          Features of Pokemon Entropy

                                          The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                                          Reply With Quote
                                            #21    
                                          Old August 24th, 2016 (7:27 AM).
                                          BlackOutG5's Avatar
                                          BlackOutG5 BlackOutG5 is offline
                                             
                                            Join Date: Jul 2015
                                            Gender: Male
                                            Nature: Bold
                                            Posts: 77
                                            Ok, here's my fix to make it work just add or edit the links in red! All of this is in PSystem_Utilities The only problem with this fix is that Shadow Pokemon's Icons and sprites won't load thats the only fix everything else from Delta/Alolan icons and so on will load.

                                            1) Search for # Loads Pokémon/item/trainer graphics

                                            After than Search for def pbLoadPokemonBitmapSpecies(pokemon, species, back=false)

                                            then replace it with this pastebin all the way to def pbPokemonFootprintFile(species) BUT DONT REPLACE THE FOOTPRINT Script just everything from the pbLoadPokemonBitmapSpecies and everything between those 2. Dont forget to copy raw of the pastebin: http://pastebin.com/Q4DPb57W
                                            Reply With Quote
                                              #22    
                                            Old August 24th, 2016 (10:21 AM).
                                            Rot8er_ConeX's Avatar
                                            Rot8er_ConeX Rot8er_ConeX is offline
                                               
                                              Join Date: May 2015
                                              Location: The Dissa Region
                                              Gender: Male
                                              Posts: 822
                                              Quote:
                                              Originally Posted by BlackOutG5 View Post
                                              Ok, here's my fix to make it work just add or edit the links in red! All of this is in PSystem_Utilities The only problem with this fix is that Shadow Pokemon's Icons and sprites won't load thats the only fix everything else from Delta/Alolan icons and so on will load.

                                              1) Search for # Loads Pokémon/item/trainer graphics

                                              After than Search for def pbLoadPokemonBitmapSpecies(pokemon, species, back=false)

                                              then replace it with this pastebin all the way to def pbPokemonFootprintFile(species) BUT DONT REPLACE THE FOOTPRINT Script just everything from the pbLoadPokemonBitmapSpecies and everything between those 2. Dont forget to copy raw of the pastebin: http://pastebin.com/Q4DPb57W
                                              So I'm looking at the code for the EBS and even of vanilla Essentials v16.2 And I'm not seeing either of them mention anything about sorting the Pokemon sprites into separate folders based on shininess and gender. That might be something you yourself added.

                                              The issue I noticed, which does coincide with the error message originally posted (4 arguments in a function designed to take in at most 3), is that the EBS has a way to handle the scale of sprites whereas default Essentials doesn't.

                                              Somehow, though (don't ask me how), you reminded me that I need to add compatibility for the Following Pokemon script.
                                              __________________
                                              Features of Pokemon Entropy

                                              The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                                              Reply With Quote
                                                #23    
                                              Old August 24th, 2016 (11:31 AM).
                                              BlackOutG5's Avatar
                                              BlackOutG5 BlackOutG5 is offline
                                                 
                                                Join Date: Jul 2015
                                                Gender: Male
                                                Nature: Bold
                                                Posts: 77
                                                Oh EBS I'm using BW Essentials edited by Klien xD. That's a fix for people who use BW essentials. version 3.1.1
                                                Reply With Quote
                                                  #24    
                                                Old August 24th, 2016 (11:55 AM). Edited August 24th, 2016 by Rot8er_ConeX.
                                                Rot8er_ConeX's Avatar
                                                Rot8er_ConeX Rot8er_ConeX is offline
                                                   
                                                  Join Date: May 2015
                                                  Location: The Dissa Region
                                                  Gender: Male
                                                  Posts: 822
                                                  Quote:
                                                  Originally Posted by BlackOutG5 View Post
                                                  Oh EBS I'm using BW Essentials edited by Klien xD. That's a fix for people who use BW essentials. version 3.1.1
                                                  That's good to know. That's the only thing that makes this incompatible with BW Essentials?

                                                  I'll have to figure out how to detect if someone is using BW essentials. Detecting the EBS is as simple as checking if the class DynamicPokemonSprite exists, according to other things Luka's made.

                                                  Which leads to my next point: the first post now contains code that makes it compatible with the EBS and Following Pokemon.
                                                  __________________
                                                  Features of Pokemon Entropy

                                                  The black circular "doodles" in the lower right corner of my avatar are actually my username written in Gallifreyan. Yes I'm a Whovian.
                                                  Reply With Quote
                                                    #25    
                                                  Old August 24th, 2016 (3:39 PM).
                                                  BlackOutG5's Avatar
                                                  BlackOutG5 BlackOutG5 is offline
                                                     
                                                    Join Date: Jul 2015
                                                    Gender: Male
                                                    Nature: Bold
                                                    Posts: 77
                                                    It works now I re-added you script to my game and as well as the EliteBattle_BitmapWrappers but got another issue It won't load the right image like it would still be the regular pokemon instead of the alolan pokemon when I look at it in battle or Party. but the Icon loads perfectly fine. and the type change and moves work too.
                                                    Reply With Quote
                                                    Reply

                                                    Quick Reply

                                                    Join the conversation!

                                                    Create an account to post a reply in this thread, participate in other discussions, and more!

                                                    Create a PokéCommunity Account
                                                    Thread Tools

                                                    Posting Rules
                                                    You may not post new threads
                                                    You may not post replies
                                                    You may not post attachments
                                                    You may not edit your posts

                                                    BB code is On
                                                    Smilies are On
                                                    [IMG] code is On
                                                    HTML code is Off

                                                    Forum Jump


                                                    All times are GMT -8. The time now is 10:47 AM.