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

    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
    • UK
    • Seen Apr 19, 2024
    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
    • UK
    • Seen Apr 19, 2024
    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
    • UK
    • Seen Apr 19, 2024
    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