• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • 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

1,405
Posts
11
Years
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.
 

Florio

Pokemon Crimson Skies Owner
391
Posts
15
Years
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.
 
199
Posts
14
Years
  • Seen Jul 6, 2022
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:

Maruno

Lead Dev of Pokémon Essentials
5,285
Posts
16
Years
p0.moves = PBMoves::THUNDER
p0.moves = PBMoves::SURF
p0.moves = PBMoves::GRASSKNOT
p0.moves = PBMoves::HIDDENPOWER
That's not how you teach moves to a Pokémon. Try reading the Essentials wiki and/or looking at how the demo Pokémon are given movesets full of HMs (in def pbCreatePokemon).
 

NeoPlayerX

Julie_Haru
9
Posts
9
Years
  • Age 24
  • Seen Mar 12, 2023
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
 
20
Posts
9
Years
  • Age 43
  • Seen Apr 26, 2020
it might be possible to add that the duelist just sees the player approaches to fight
 
824
Posts
8
Years
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:
22
Posts
8
Years
  • Age 23
  • Seen Feb 1, 2017
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.
 
824
Posts
8
Years
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
 
22
Posts
8
Years
  • Age 23
  • Seen Feb 1, 2017
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
 
Back
Top