• 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.

VS sequences, done right

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
vs.png
This tutorial/script aims to help you create a B/W styled Gym Leader VS sequence, no matter what your screen size. NOTE: this script will only coordinate properly if you use a single screen layout!

First collect the example files I made for this VS sequence. Next extract the files in their correct folders. If you look at the files, trainer_0.png and trainer_1.png are the default files for the Player trainer, same goes with bar_0.png and bar_1.png. The numbers 0 and 1 stand for the Player's trainer ID which you have defined in the metadata.txt. If you have changed these values, change the values of the images accordingly. For ideal results the dimensions of both the bars and sprites should be (Graphics.width/2) x 128. Height of the sprites can be greater than 128, but the script will cut them to the preferred height.

Next, go to the script PokemonTrainers and look for
Code:
def pbTrainerBattle
which should be around line 288. Somewhere around line 409, you need to replace
Code:
pbBattleAnimation(trainerbgm)
with
Code:
pbBattleAnimation(trainerbgm,trainerid,trainername)
within that def

Now, go to the script PokemonField and look for
Code:
def pbBattleAnimation
which should be somewhere around line 613. Replace this line with the line
Code:
def pbBattleAnimation(bgm=nil,trainerid=-1,trainername="")
Directly under this, add the code
Code:
gym=true if FileTest.exist?("Graphics/VS/trainer_#{trainerid}.png") && FileTest.exist?("Graphics/VS/bar_#{trainerid}.png") # If all graphics are present, sequence will activate
for i in RIVALNAMES
  if isConst?(trainerid,PBTrainers,i[0]) && $game_variables[i[1]]!=0
    trainername=$game_variables[i[1]] # Handles rival names
  end
end
All you have to do now, is have the trainer_ and bar_ images within the "VS" folder, where the trainer ID of the battler with the VS sequence follows the _.

Next, in the same script, find
Code:
if Sprite.method_defined?(:wave_amp) && rand(15)==0
      viewport.color=Color.new(0,0,0,255)
      sprite = Sprite.new
      bitmap=Graphics.snap_to_bitmap
      bm=bitmap.clone
      sprite.z=99999
      sprite.bitmap = bm
      sprite.wave_speed=500
      for i in 0..25
        sprite.opacity-=10
        sprite.wave_amp+=60
        sprite.update
        sprite.wave_speed+=30
        2.times do
          Graphics.update
        end
      end
      bitmap.dispose
      bm.dispose
      sprite.dispose
which should start somewhere around line 670 and under this entire chunk paste the following script
Code:
 elsif gym==true
      baseColor=Color.new(248,248,248)
      shadowColor=Color.new(12*6,12*6,12*6)
      viewplayer=Viewport.new(0,Graphics.height/3,Graphics.width/2,128)
      viewplayer.z=viewport.z
      viewopp=Viewport.new(Graphics.width/2,Graphics.height/3,Graphics.width/2,128)
      viewopp.z=viewport.z
      viewvs=Viewport.new(0,0,Graphics.width,Graphics.height)
      viewvs.z=viewport.z
      xoffset=(Graphics.width/2)/10
      xoffset=xoffset.round
      xoffset=xoffset*10
      
      fade=Sprite.new(viewport)
      fade.bitmap=BitmapCache.load_bitmap("Graphics/VS/flash")
      fade.tone=Tone.new(-255,-255,-255)
      fade.opacity=100
      overlay=Sprite.new(viewport)
      overlay.bitmap=Bitmap.new(Graphics.width,Graphics.height)
      pbSetSystemFont(overlay.bitmap)
      
      bar1=Sprite.new(viewplayer)
      bar1.bitmap=BitmapCache.load_bitmap("Graphics/VS/bar_#{$Trainer.trainertype}")
      bar1.x=-xoffset
      bar2=Sprite.new(viewopp)
      bar2.bitmap=BitmapCache.load_bitmap("Graphics/VS/bar_#{trainerid}")
      bar2.x=xoffset
      
      vs=Sprite.new(viewvs)
      vs.bitmap=BitmapCache.load_bitmap("Graphics/VS/vs_gym")
      vs.ox=vs.bitmap.width/2
      vs.oy=vs.bitmap.height/2
      vs.x=Graphics.width/2
      vs.y=Graphics.height/1.5
      vs.visible=false
      
      flash=Sprite.new(viewvs)
      flash.bitmap=BitmapCache.load_bitmap("Graphics/VS/flash")
      flash.opacity=0
      
      10.times do
        bar1.x+=xoffset/10
        bar2.x-=xoffset/10
        pbWait(1)
      end
      pbSEPlay("Flash2")
      pbSEPlay("Sword2")
      flash.opacity=255
      bar1=AnimatedPlane.new(viewplayer)
      bar1.bitmap=BitmapCache.load_bitmap("Graphics/VS/bar_#{$Trainer.trainertype}")
      player=Sprite.new(viewplayer)
      player.bitmap=BitmapCache.load_bitmap("Graphics/VS/trainer_#{$Trainer.trainertype}")
      player.x=-xoffset
      bar2=AnimatedPlane.new(viewopp)
      bar2.bitmap=BitmapCache.load_bitmap("Graphics/VS/bar_#{trainerid}")
      trainer=Sprite.new(viewopp)
      trainer.bitmap=BitmapCache.load_bitmap("Graphics/VS/trainer_#{trainerid}")
      trainer.x=xoffset
      trainer.tone=Tone.new(-255,-255,-255)
      15.times do
        flash.opacity-=51
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      10.times do
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      11.times do
        bar1.ox-=16
        player.x+=xoffset/10
        trainer.x-=xoffset/10
        bar2.ox+=16
        pbWait(1)
      end
      2.times do
        bar1.ox-=16
        player.x-=xoffset/20
        trainer.x+=xoffset/20
        bar2.ox+=16
        pbWait(1)
      end
      10.times do
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      val=2
      flash.opacity=255
      vs.visible=true
      trainer.tone=Tone.new(0,0,0)
      textpos=[
      [_INTL("{1}",$Trainer.name),Graphics.width/4,(Graphics.height/1.5)+10,2,baseColor,shadowColor],
      [_INTL("{1}",trainername),(Graphics.width/4)+(Graphics.width/2),(Graphics.height/1.5)+10,2,baseColor,shadowColor]
      ]
      pbDrawTextPositions(overlay.bitmap,textpos)
      pbSEPlay("Sword2")
      10.times do
        flash.opacity-=25.5
        vs.x+=val
        vs.y-=val
        val=2 if vs.x<=256-2
        val=-2 if vs.x>=256+2
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      60.times do
        vs.x+=val
        vs.y-=val
        val=2 if vs.x<=256-2
        val=-2 if vs.x>=256+2
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      30.times do
        bar1.ox-=16
        bar2.ox+=16
        vs.zoom_x+=0.2
        vs.zoom_y+=0.2
        pbWait(1)
      end
      flash.tone=Tone.new(-255,-255,-255)
      10.times do
        flash.opacity+=25.5
        bar1.ox-=16
        bar2.ox+=16
        pbWait(1)
      end
      
      fade.dispose
      overlay.dispose
      bar1.dispose
      bar2.dispose
      player.dispose
      trainer.dispose
      vs.dispose
      flash.dispose
      viewplayer.dispose
      viewopp.dispose
      viewvs.dispose

That is all. There is no further need to externally call the script at all. Just create the corresponding images, and the script will do the rest. Every time when you battle a trainer, who's ID corresponds to one of the IDs you have included with the graphics, the game will load up a VS sequence. Unless you've done something wrong during your steps, you shouldn't experience any problems with this script. It is quite simple, and saves the user some hassle.

Perhaps if Maruno sees it and likes it, he could incorporate it in the next version of Essentials, but with it being triggered through some edits with the "trainertypes.txt" file. I already know how it can be done, but I didn't want to post that method as it requires changes to the PokemonCompiler.
 
Last edited:

Lord Varion

Guess who's back?
2,642
Posts
15
Years
  • Age 29
  • Seen Jan 6, 2015
nlzCq.jpg


Im not good at this stuff. At all.
But follwing everything you wrote above, I get this message when trying to activate the battle.
 

venom12

Pokemon Crystal Rain Relased
476
Posts
17
Years
  • Age 33
  • Seen Dec 28, 2023
Just simply put under
Code:
  flash=Sprite.new(viewvs)
      flash.bitmap=BitmapCache.load_bitmap("Graphics/VS/flash")
      flash.opacity=0
Code:
baseColor=Color.new(248,248,248)
 shadowColor=Color.new(104,88,112)
 

Maruno

Lead Dev of Pokémon Essentials
5,285
Posts
16
Years
Perhaps if Maruno sees it and likes it, he could incorporate it in the next version of Essentials, but with it being triggered through some edits with the "trainertypes.txt" file. I already know how it can be done, but I didn't want to post that method as it requires changes to the PokemonCompiler.
Enlighten me, what changes are necessary? I can't see any.

Also, rather than having an array of Gym Leader trainer types, couldn't you simply automate it by checking whether the appropriate graphics exist? If they all do, show the animation, and if not, do things as normal. Hint: loading Pokémon sprites do this checking to make sure they only load sprites which exist.

Every time I see someone making a Vs. animation, it's different. That was one of the things putting me off. However, I'll look into it.
 

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
Im not good at this stuff. At all.
But follwing everything you wrote above, I get this message when trying to activate the battle.

That is my mistake. I overlooked the colors. You just need to add
Code:
baseColor=Color.new(248,248,248)
shadowColor=Color.new(12*6,12*6,12*6)
anywhere at the beginning of the new code section or just simply copy and paste the new amended code.

Enlighten me, what changes are necessary? I can't see any.

Also, rather than having an array of Gym Leader trainer types, couldn't you simply automate it by checking whether the appropriate graphics exist? If they all do, show the animation, and if not, do things as normal. Hint: loading Pokémon sprites do this checking to make sure they only load sprites which exist.

Every time I see someone making a Vs. animation, it's different. That was one of the things putting me off. However, I'll look into it.

I could do the graphics checking, but I was thinking of another easy alternative. In the "trainertypes.txt", you could add one optional value which would either read true or false (this would be the field right after the gender type), which (I believe) could make it easier on the users to set whether or not that particular trainer type does have a VS sequence (which is where the Compiler would need to be edited, in order to save another extra field to the "trainertypes.dat"). But actually, I think I'll just go with your image checking option. I haven't thought of it, and it sounds like a much less complicated method.

EDIT: @Maruno, now I remember why I did it with the arrays. Since in my game I use multiple, different VS sequences (Champion, Gym Leaders, misc), I separated my stuff with arrays. And this was a port and modification of what I did originally.
 
Last edited:

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
I really suck at this, any clue what to do now?

Just replace the VS code you have now, with my amended code (last code box). See if that solves it. You shouldn't get a "dispose" error unless you deleted one of the sprite definitions.
 

Lord Varion

Guess who's back?
2,642
Posts
15
Years
  • Age 29
  • Seen Jan 6, 2015
pokemon_eon___vs_sequence_by_nintendork15-d5o0adw.png


There we go it works now!

It's a great tutorial, none the less.
 

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
There we go it works now!

It's a great tutorial, none the less.

Great to know! You might just want to increase the width of both the sprites to 256 px and reposition them, since the script doesn't do that :P Also, maybe add those "white bars" within the VS bars themselves. The script would animate that to scroll nicely.
 

Maruno

Lead Dev of Pokémon Essentials
5,285
Posts
16
Years
I could do the graphics checking, but I was thinking of another easy alternative. In the "trainertypes.txt", you could add one optional value which would either read true or false (this would be the field right after the gender type), which (I believe) could make it easier on the users to set whether or not that particular trainer type does have a VS sequence (which is where the Compiler would need to be edited, in order to save another extra field to the "trainertypes.dat"). But actually, I think I'll just go with your image checking option. I haven't thought of it, and it sounds like a much less complicated method.

EDIT: @Maruno, now I remember why I did it with the arrays. Since in my game I use multiple, different VS sequences (Champion, Gym Leaders, misc), I separated my stuff with arrays. And this was a port and modification of what I did originally.
I see. I suppose you still could have used my method by having each different animation use different graphics names (e.g. "bar_#{trainerid}" and "bar2_#{trainerid}"), but that's just a slight convenience.
 
772
Posts
13
Years
  • Age 35
  • UK
  • Seen today
This is cool. The only problem with it is it doesn't seem to take into account if you use the RIVALNAMES array. I have my rival set up with the name ??? which is then set using the array, but on the VS it shows ??? instead of the actual name
 

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
This is cool. The only problem with it is it doesn't seem to take into account if you use the RIVALNAMES array. I have my rival set up with the name ??? which is then set using the array, but on the VS it shows ??? instead of the actual name

Hmm, I haven't thought of that. You can just add
Code:
for i in 0...(RIVALNAMES.length)
    trainername=$game_variables[RIVALNAMES[i][1]] if trainerid==PBTrainers:RIVALNAMES[i][0]
  end
somewhere before the VS sequence, and I think that should work fine.

My only problem with this is the fact that you can't use bars like these.

This is designed to help you create 5th gen Gym Leader styled VS sequence. And that is exactly what it does. If you want to use differently designed/animated VS sequences, you'd either have to tweak this one, or create it yourself.
 
772
Posts
13
Years
  • Age 35
  • UK
  • Seen today
Hmm, I haven't thought of that. You can just add
Code:
for i in 0...(RIVALNAMES.length)
    trainername=$game_variables[RIVALNAMES[i][1]] if trainerid==PBTrainers:RIVALNAMES[i][0]
  end
somewhere before the VS sequence, and I think that should work fine.

That's giving a syntax error
 

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
That's giving a syntax error

Right. I've looked at how Maruno did it, so, yeah. I actually never knew how those Rival names were handled :/ Anyway, the following should work

Code:
for i in RIVALNAMES
  if isConst?(trainerid,PBTrainers,i[0]) && $game_variables[i[1]]!=0
    trainername=$game_variables[i[1]]
  end
end
 

Crystal Noel

RPG Maker VX Ace Scripter
222
Posts
11
Years
I think maybe what caused it was the RIVALNAMES.length. I usually use something like this.
Code:
for i in 0...$game_party.battle_members.size
  $game_party.members[i].increase_steps
end
I got that right from a Crystal Engine Script, so this is in VX Ace not XP, but the difference between the two is mainly how the default scripts are set up.
 

Luka S.J.

Jealous Croatian
1,270
Posts
15
Years
I think maybe what caused it was the RIVALNAMES.length. I usually use something like this.
Code:
for i in 0...$game_party.battle_members.size
  $game_party.members[i].increase_steps
end
I got that right from a Crystal Engine Script, so this is in VX Ace not XP, but the difference between the two is mainly how the default scripts are set up.

I don't think that caused the error, .length is the correct method to check array size. Anyway, I already posted a solution which I think should work without problems.
 
772
Posts
13
Years
  • Age 35
  • UK
  • Seen today
Right. I've looked at how Maruno did it, so, yeah. I actually never knew how those Rival names were handled :/ Anyway, the following should work

Code:
for i in RIVALNAMES
  if isConst?(trainerid,PBTrainers,i[0]) && $game_variables[i[1]]!=0
    trainername=$game_variables[i[1]]
  end
end

This works fine, thank you
 

KillerMapper

Helix Follower
200
Posts
9
Years
Did you tried using transparent bars? (without any opacity)

Or you can look in the code and remove what makes the bar display. (Search for Luka in the scripts using Ctrl+Shift+F to find it).

Also (in case of) this topic is old and the script is now in Essential, no need to manually add it.
 
Back
Top