• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Our weekly protagonist poll is now up! Vote for your favorite Conquest protagonist in the poll by clicking here.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Custom trainer battles

You should put the example trainer type to a 1-71 number because otherwise people trying the script out without changing it will get an error saying the trainer type doesn't exist (in the most complicated error possible)

Scripts works fine and i will def use it in my Pokemon game(with credit of course) to save time making trainer battles.
 
What program are you using for this because it looks unfamiliar
 
And is it worth paying $70 to get
 
One website was actually selling it for 70$ I was looking at it but it didn't seem right
 
Honestly this script seems somewhat unnecessary. Editing the PBS is easy enough, and if you make your Trainer's VIA this method then you can't easily change the Pokemon after. Sometimes I change around the Pokemon in my game and the Trainer's to and Ctrl+H and Ctrl+F come in handy while using the trainers PBS file. I feel like this would make the game more unorganized overall. But still, it seems useful for people who aren't as accustomed to Essentials.
 
I tried to create a trainer but it causes error message.

Spoiler:


Spoiler:



EDIT: I changed "pokemon.calcStats" for "p0.calcStats" and it fixed up.
But when the trainer is going to use the Pokemon in battle, another error message:

Spoiler:
 
Last edited:
Sure, it's not hard. Insert this method in the script.

Code:
# ------------------------------------------------------------------------------
# Returns a random element from a given array.
# ------------------------------------------------------------------------------
def randomElement(array)
  i = rand(array.length)
  return array[i]
end

Then, in the event, instead of writing createPokemon("PIKACHU", 13) you can write
createPokemon(randomElement(SomePool), 13), and you'll need to define 'SomePool',
either in the event script or in a global script (such as CustomTrainers) as,
Code:
SomePool = ["PIKACHU", "BULBASAUR", "SOME_OTHER_POKEMON"]



Sorry, I don't understand. Do you want me to describe functions better?

To put all the Pokémon at once in the "array" instead of putting one by one?

Instead of placing: SomePool = [Bulbasaur, Ivysaur ...]
Place: SomePool = [Bulbasaur ... Zygard]

It's possible?

Thanks
 
it might be possible to add that the duelist just sees the player approaches to fight
 
Honestly this script seems somewhat unnecessary. Editing the PBS is easy enough, and if you make your Trainer's VIA this method then you can't easily change the Pokemon after. Sometimes I change around the Pokemon in my game and the Trainer's to and Ctrl+H and Ctrl+F come in handy while using the trainers PBS file. I feel like this would make the game more unorganized overall. But still, it seems useful for people who aren't as accustomed to Essentials.

I plan on using this only for "dynamic" trainers. Characters like your rival where your choices affect their party. Rather than defining a slot for him in the PBS files for each encounter, each starter, and each Eeveeloution, and have a convoluted mess of conditional branches in each event, I'm going to just have him dynamically create his party at each encounter. You picked this starter? Okay, add these two pokemon to his party. You evolved your plot Eevee into this? Add these two pokemon. You're playing as a female? Make this member of his team male.

Standard trainers who are going to have the same Pokemon no matter what you choose see going to stay in the PBS files.
 
Last edited:
Is there a way to add support for the gen 6 battle mechanics, the one's found in the pokemon essentials gen6.
Amazing job by the way.
 
Is there a way to add support for the gen 6 battle mechanics, the one's found in the pokemon essentials gen6.
Amazing job by the way.

Code:
# ------------------------------------------------------------------------------
# Written by Stochastic, except for customTrainerBattle method which is a
# modified version of pbTrainerBattle method.
# ------------------------------------------------------------------------------

BR_DRAW = 5
BR_LOSS = 2
BR_WIN = 1

# ------------------------------------------------------------------------------
# species - Name of the species, e.g. "PIKACHU"
# level - Level
# moveset - Optional. Array of moves, e.g. [:MUDSLAP, :THUNDERBOLT, :VINEWHIP]
# If not specified, pokemon will be created with moves learned by leveling.
# The pokemon doesn't need to be able to learn the given moves, they can be
# arbitary.
# ------------------------------------------------------------------------------
def createPokemon(species, level, moveset=nil)
  begin
    poke = PokeBattle_Pokemon.new(species, level)
    poke.moves = convertMoves(moveset) if moveset
    poke.shinyflag = false
    return poke
  rescue
    return PokeBattle_Pokemon.new("PIKACHU", 5)
  end
end

def convertMoves(moves)
  moves.map! {|m| PBMove.new(getMoveID(m))}
  return moves
end

# provide move like this; :TACKLE
def getMoveID(move)
  return getConst(PBMoves,move)
end

# ------------------------------------------------------------------------------
# Creates a trainer with specified id, name, party, and optionally, items.
# Does not depend on defined trainers, only on trainer types
# ------------------------------------------------------------------------------
def createTrainer(trainerid,trainername,party,items=[])
  
  name = pbGetMessageFromHash(MessageTypes::TrainerNames, trainername)
  opponent = PokeBattle_Trainer.new(name, trainerid)
  opponent.setForeignID($Trainer) if $Trainer
  opponent.party = party
  
  return [opponent,items,party]
end

# ------------------------------------------------------------------------------
# Initiates trainer battle. This is a modified pbTrainerBattle method.
#
# trainer - custom PokeBattle_Trainer provided by the user
# endspeech - what the trainer says in-battle when defeated
# doublebattle - Optional. Set it to true if you want a double battle
# canlose - Optional. Set it to true if you want your party to be healed after battle,
# and if you don't want to be sent to a pokemon center if you lose
# ------------------------------------------------------------------------------
def customTrainerBattle(trainer,endspeech,doublebattle=false,canlose=false,
                        skybattle=false,inverse=false)
   # Sky battle eligibility for player
  if skybattle
    count=0
    for poke in $Trainer.party
      count+=1 if pbCanSkyBattle?(poke)
    end
    if count==0
      Kernel.pbMessage(_INTL("You don't have any eligible pokemon for a sky battle"))
      return false
    end
  end
  trainerparty=0 # added by SH
  if $Trainer.pokemonCount==0
    Kernel.pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG
    return BR_LOSS # changed by SH
  end
  if !$PokemonTemp.waitingTrainer && $Trainer.ablePokemonCount>1 &&
    pbMapInterpreterRunning?
    thisEvent=pbMapInterpreter.get_character(0)
    triggeredEvents=$game_player.pbTriggeredTrainerEvents([2],false)
    otherEvent=[]
    for i in triggeredEvents
      if i.id!=thisEvent.id && !$game_self_switches[[$game_map.map_id,i.id,"A"]]
        otherEvent.push(i)
      end
    end
    if otherEvent.length==1
      if trainer[2].length<=3
        $PokemonTemp.waitingTrainer=[trainer,thisEvent.id,endspeech,doublebattle]
        return BR_LOSS # changed by SH
      end
    end
  end
  
  if $PokemonGlobal.partner && ($PokemonTemp.waitingTrainer || doublebattle)
    othertrainer=PokeBattle_Trainer.new(
      $PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
    othertrainer.id=$PokemonGlobal.partner[2]
    othertrainer.party=$PokemonGlobal.partner[3]
    playerparty=[]
    for i in 0...$Trainer.party.length
      playerparty[i]=$Trainer.party[i]
    end
    for i in 0...othertrainer.party.length
      playerparty[6+i]=othertrainer.party[i]
    end
    fullparty1=true
    playertrainer=[$Trainer,othertrainer]
    doublebattle=true
  else
    playerparty=$Trainer.party
    playertrainer=$Trainer
    fullparty1=false
  end
  if $PokemonTemp.waitingTrainer
    combinedParty=[]
    fullparty2=false
    if false
      if $PokemonTemp.waitingTrainer[0][2].length>3
        raise _INTL("Opponent 1's party has more than three Pokémon, which is not allowed")
      end
      if trainer[2].length>3
        raise _INTL("Opponent 2's party has more than three Pokémon, which is not allowed")
      end
    elsif $PokemonTemp.waitingTrainer[0][2].length>3 || trainer[2].length>3
      for i in 0...$PokemonTemp.waitingTrainer[0][2].length
        combinedParty[i]=$PokemonTemp.waitingTrainer[0][2][i]
      end
      for i in 0...trainer[2].length
        combinedParty[6+i]=trainer[2][i]
      end
      fullparty2=true
    else
      for i in 0...$PokemonTemp.waitingTrainer[0][2].length
        combinedParty[i]=$PokemonTemp.waitingTrainer[0][2][i]
      end
      for i in 0...trainer[2].length
        combinedParty[3+i]=trainer[2][i]
      end
      fullparty2=false
    end
    #Sky battle eligibility for opponent
    if skybattle
      count=0
      for poke in combinedParty
        count+=1 if pbCanSkyBattle?(poke)
      end
      if count==0
        Kernel.pbMessage(_INTL("The opponents don't have any eligible pokemon for a sky battle"))
        return false
      end
    end
    scene=pbNewBattleScene
    battle=PokeBattle_Battle.new(scene,playerparty,combinedParty,playertrainer,
      [$PokemonTemp.waitingTrainer[0][0],trainer[0]],skybattle,inverse,gen)
    trainerbgm=pbGetTrainerBattleBGM(
      [$PokemonTemp.waitingTrainer[0][0],trainer[0]])
    battle.fullparty1=fullparty1
    battle.fullparty2=fullparty2
    battle.doublebattle=battle.pbDoubleBattleAllowed?()
    battle.endspeech=$PokemonTemp.waitingTrainer[2]
    battle.endspeech2=endspeech
    battle.items=[$PokemonTemp.waitingTrainer[0][1],trainer[1]]
  else
    #Sky battle eligibility for opponent
    if skybattle
      count=0
      for poke in trainer[2]
        count+=1 if pbCanSkyBattle?(poke)
      end
      if count==0
        Kernel.pbMessage(_INTL("The opponents don't have any eligible pokemon for a sky battle"))
        return false
      end
    end
    scene=pbNewBattleScene
    battle=PokeBattle_Battle.new(scene,playerparty,trainer[2],playertrainer,trainer[0],skybattle,inverse)
    battle.fullparty1=fullparty1
    battle.doublebattle=doublebattle ? battle.pbDoubleBattleAllowed?() : false
    battle.endspeech=endspeech
    battle.items=trainer[1]
    trainerbgm=pbGetTrainerBattleBGM(trainer[0])
  end
  if Input.press?(Input::CTRL) && $DEBUG
    Kernel.pbMessage(_INTL("SKIPPING BATTLE..."))
    Kernel.pbMessage(_INTL("AFTER LOSING..."))
    Kernel.pbMessage(battle.endspeech)
    Kernel.pbMessage(battle.endspeech2) if battle.endspeech2
    if $PokemonTemp.waitingTrainer
      pbMapInterpreter.pbSetSelfSwitch(
        $PokemonTemp.waitingTrainer[1],"A",true
      )
      $PokemonTemp.waitingTrainer=nil
    end
    return BR_WIN # changed by SH
  end
  Events.onStartBattle.trigger(nil,nil)
  battle.internalbattle=true
  pbPrepareBattle(battle)
  restorebgm=true
  decision=0
  pbBattleAnimation(trainerbgm,trainer[0].trainertype,trainer[0].name) { 
    pbSceneStandby {
        decision=battle.pbStartBattle(canlose)
    }
    if $PokemonGlobal.partner
      pbHealAll
      for i in $PokemonGlobal.partner[3]; i.heal; end
    end
    if decision==2 || decision==5
      if canlose
        for i in $Trainer.party; i.heal; end
        for i in 0...10
          Graphics.update
        end
      else
        $game_system.bgm_unpause
        $game_system.bgs_unpause
        Kernel.pbStartOver
      end
    else
      Events.onEndBattle.trigger(nil,decision)
      if decision==1
        if $PokemonTemp.waitingTrainer
          pbMapInterpreter.pbSetSelfSwitch(
              $PokemonTemp.waitingTrainer[1],"A",true
          )
        end
      end
    end
  }
  Input.update
  $PokemonTemp.waitingTrainer=nil
  return decision  # changed by SH
end
 
Code:
# ------------------------------------------------------------------------------
# Written by Stochastic, except for customTrainerBattle method which is a
# modified version of pbTrainerBattle method.
# ------------------------------------------------------------------------------

BR_DRAW = 5
BR_LOSS = 2
BR_WIN = 1

# ------------------------------------------------------------------------------
# species - Name of the species, e.g. "PIKACHU"
# level - Level
# moveset - Optional. Array of moves, e.g. [:MUDSLAP, :THUNDERBOLT, :VINEWHIP]
# If not specified, pokemon will be created with moves learned by leveling.
# The pokemon doesn't need to be able to learn the given moves, they can be
# arbitary.
# ------------------------------------------------------------------------------
def createPokemon(species, level, moveset=nil)
  begin
    poke = PokeBattle_Pokemon.new(species, level)
    poke.moves = convertMoves(moveset) if moveset
    poke.shinyflag = false
    return poke
  rescue
    return PokeBattle_Pokemon.new("PIKACHU", 5)
  end
end

def convertMoves(moves)
  moves.map! {|m| PBMove.new(getMoveID(m))}
  return moves
end

# provide move like this; :TACKLE
def getMoveID(move)
  return getConst(PBMoves,move)
end

# ------------------------------------------------------------------------------
# Creates a trainer with specified id, name, party, and optionally, items.
# Does not depend on defined trainers, only on trainer types
# ------------------------------------------------------------------------------
def createTrainer(trainerid,trainername,party,items=[])
  
  name = pbGetMessageFromHash(MessageTypes::TrainerNames, trainername)
  opponent = PokeBattle_Trainer.new(name, trainerid)
  opponent.setForeignID($Trainer) if $Trainer
  opponent.party = party
  
  return [opponent,items,party]
end

# ------------------------------------------------------------------------------
# Initiates trainer battle. This is a modified pbTrainerBattle method.
#
# trainer - custom PokeBattle_Trainer provided by the user
# endspeech - what the trainer says in-battle when defeated
# doublebattle - Optional. Set it to true if you want a double battle
# canlose - Optional. Set it to true if you want your party to be healed after battle,
# and if you don't want to be sent to a pokemon center if you lose
# ------------------------------------------------------------------------------
def customTrainerBattle(trainer,endspeech,doublebattle=false,canlose=false,
                        skybattle=false,inverse=false)
   # Sky battle eligibility for player
  if skybattle
    count=0
    for poke in $Trainer.party
      count+=1 if pbCanSkyBattle?(poke)
    end
    if count==0
      Kernel.pbMessage(_INTL("You don't have any eligible pokemon for a sky battle"))
      return false
    end
  end
  trainerparty=0 # added by SH
  if $Trainer.pokemonCount==0
    Kernel.pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG
    return BR_LOSS # changed by SH
  end
  if !$PokemonTemp.waitingTrainer && $Trainer.ablePokemonCount>1 &&
    pbMapInterpreterRunning?
    thisEvent=pbMapInterpreter.get_character(0)
    triggeredEvents=$game_player.pbTriggeredTrainerEvents([2],false)
    otherEvent=[]
    for i in triggeredEvents
      if i.id!=thisEvent.id && !$game_self_switches[[$game_map.map_id,i.id,"A"]]
        otherEvent.push(i)
      end
    end
    if otherEvent.length==1
      if trainer[2].length<=3
        $PokemonTemp.waitingTrainer=[trainer,thisEvent.id,endspeech,doublebattle]
        return BR_LOSS # changed by SH
      end
    end
  end
  
  if $PokemonGlobal.partner && ($PokemonTemp.waitingTrainer || doublebattle)
    othertrainer=PokeBattle_Trainer.new(
      $PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
    othertrainer.id=$PokemonGlobal.partner[2]
    othertrainer.party=$PokemonGlobal.partner[3]
    playerparty=[]
    for i in 0...$Trainer.party.length
      playerparty[i]=$Trainer.party[i]
    end
    for i in 0...othertrainer.party.length
      playerparty[6+i]=othertrainer.party[i]
    end
    fullparty1=true
    playertrainer=[$Trainer,othertrainer]
    doublebattle=true
  else
    playerparty=$Trainer.party
    playertrainer=$Trainer
    fullparty1=false
  end
  if $PokemonTemp.waitingTrainer
    combinedParty=[]
    fullparty2=false
    if false
      if $PokemonTemp.waitingTrainer[0][2].length>3
        raise _INTL("Opponent 1's party has more than three Pokémon, which is not allowed")
      end
      if trainer[2].length>3
        raise _INTL("Opponent 2's party has more than three Pokémon, which is not allowed")
      end
    elsif $PokemonTemp.waitingTrainer[0][2].length>3 || trainer[2].length>3
      for i in 0...$PokemonTemp.waitingTrainer[0][2].length
        combinedParty[i]=$PokemonTemp.waitingTrainer[0][2][i]
      end
      for i in 0...trainer[2].length
        combinedParty[6+i]=trainer[2][i]
      end
      fullparty2=true
    else
      for i in 0...$PokemonTemp.waitingTrainer[0][2].length
        combinedParty[i]=$PokemonTemp.waitingTrainer[0][2][i]
      end
      for i in 0...trainer[2].length
        combinedParty[3+i]=trainer[2][i]
      end
      fullparty2=false
    end
    #Sky battle eligibility for opponent
    if skybattle
      count=0
      for poke in combinedParty
        count+=1 if pbCanSkyBattle?(poke)
      end
      if count==0
        Kernel.pbMessage(_INTL("The opponents don't have any eligible pokemon for a sky battle"))
        return false
      end
    end
    scene=pbNewBattleScene
    battle=PokeBattle_Battle.new(scene,playerparty,combinedParty,playertrainer,
      [$PokemonTemp.waitingTrainer[0][0],trainer[0]],skybattle,inverse,gen)
    trainerbgm=pbGetTrainerBattleBGM(
      [$PokemonTemp.waitingTrainer[0][0],trainer[0]])
    battle.fullparty1=fullparty1
    battle.fullparty2=fullparty2
    battle.doublebattle=battle.pbDoubleBattleAllowed?()
    battle.endspeech=$PokemonTemp.waitingTrainer[2]
    battle.endspeech2=endspeech
    battle.items=[$PokemonTemp.waitingTrainer[0][1],trainer[1]]
  else
    #Sky battle eligibility for opponent
    if skybattle
      count=0
      for poke in trainer[2]
        count+=1 if pbCanSkyBattle?(poke)
      end
      if count==0
        Kernel.pbMessage(_INTL("The opponents don't have any eligible pokemon for a sky battle"))
        return false
      end
    end
    scene=pbNewBattleScene
    battle=PokeBattle_Battle.new(scene,playerparty,trainer[2],playertrainer,trainer[0],skybattle,inverse)
    battle.fullparty1=fullparty1
    battle.doublebattle=doublebattle ? battle.pbDoubleBattleAllowed?() : false
    battle.endspeech=endspeech
    battle.items=trainer[1]
    trainerbgm=pbGetTrainerBattleBGM(trainer[0])
  end
  if Input.press?(Input::CTRL) && $DEBUG
    Kernel.pbMessage(_INTL("SKIPPING BATTLE..."))
    Kernel.pbMessage(_INTL("AFTER LOSING..."))
    Kernel.pbMessage(battle.endspeech)
    Kernel.pbMessage(battle.endspeech2) if battle.endspeech2
    if $PokemonTemp.waitingTrainer
      pbMapInterpreter.pbSetSelfSwitch(
        $PokemonTemp.waitingTrainer[1],"A",true
      )
      $PokemonTemp.waitingTrainer=nil
    end
    return BR_WIN # changed by SH
  end
  Events.onStartBattle.trigger(nil,nil)
  battle.internalbattle=true
  pbPrepareBattle(battle)
  restorebgm=true
  decision=0
  pbBattleAnimation(trainerbgm,trainer[0].trainertype,trainer[0].name) { 
    pbSceneStandby {
        decision=battle.pbStartBattle(canlose)
    }
    if $PokemonGlobal.partner
      pbHealAll
      for i in $PokemonGlobal.partner[3]; i.heal; end
    end
    if decision==2 || decision==5
      if canlose
        for i in $Trainer.party; i.heal; end
        for i in 0...10
          Graphics.update
        end
      else
        $game_system.bgm_unpause
        $game_system.bgs_unpause
        Kernel.pbStartOver
      end
    else
      Events.onEndBattle.trigger(nil,decision)
      if decision==1
        if $PokemonTemp.waitingTrainer
          pbMapInterpreter.pbSetSelfSwitch(
              $PokemonTemp.waitingTrainer[1],"A",true
          )
        end
      end
    end
  }
  Input.update
  $PokemonTemp.waitingTrainer=nil
  return decision  # changed by SH
end
Thanks, it works perfectly.
And for anyone who has trouble with it, you have to show printable version.
Also the sky battle and inverse battles are the next 2 places like so:

"result = customTrainerBattle(trainer, "Oh no, you defeated me!",false,false,true,true)"
--------------------------------------------------------------------------------------------------------------|.....|
--------------------------------------------------------------------------------------------------------------^.....^
-----------------------------------------------------------------------------------------------------------sky....inverse
 
Hi, after upgrading to essentials v16 I'm receiving this error every time i use the script:
https://i.imgur.com/rz5OXlJ.png
In the essentials wiki it sais that it's due to a spelling mistake but the script worked perfectly with v15.
 
Back
Top