• Do not use Discord to host any images you post, these links expire quickly! You can learn how to add images to your posts here.
Resource icon

[v18-v18.1] Scripted and Simulated Battles 2.2

Scripted and Simulated Battles
Taking the randomness out of battles.

Description

Have you ever been this situation? In your story you have this all powerfull Pokémon Trainer and you want to show how badass they are, but all you can do is, fade the screen to black for a moment and then have your characters just comment on how tough it was? No need to pretend anymore!

With this script you can define a trainer battle and have it play out exactly the same, everytime it is started. No randomness involved. No need to rely on the AI to actually win. Making sure status conditions happen exactly when they should and Pokémon faint when they should. Ensuring Mega Evolutions at the right time and even show custom messages mid-battle!

Or maybe you even want the outcome to be random, but also want to show the battle itself. Then you can use simulated trainer battles, where the AI makes the decisions for all battlers.


What this script can do

There are several things that can be done. I tried to give as much freedom as possible, make it as easy to read for you as possible and also ensure, that the battle are only loaded when needed. Defining these takes a similar approach as the PBS files, meaning you don't ship them to the player and they are precompiled and stored in the data folder.

These are things you can define or do for every scripted battle.

WARNING: All things that are marked with an * require the ZUD Plugin! If you don't plan on using these features, you don't have to download anything else.

About trainers:
  • Use trainers from the trainers PBS file
  • Alter the party
  • Define a different end speech
  • Rename them
About Pokémon (before battle):
  • Set Item
  • Set hidden ability or second natural ability
  • Set moves (though there is no need to)
  • Set Stats
  • Set HP
  • Set Nickname
  • Or in short: everything you can already define about a Pokémon
About the battle itself:
  • Size of each side (for double/tripple/2v1 battles)
  • Variable in which the outcome shoulde be stored
  • If to use full names (incl. trainer class) for the trainers
  • re-enable random misses for accuracy checks
  • re-enable random move effects
  • re-enable random ability effects
  • re-enable random item effects
  • re-enable random-crits
  • if the battle losable
About trainer actions in the battle:
  • Use a move
  • Use a Z-Move*
  • Use a Mac-Move*
  • Use an item
  • Switch Pokémon
  • No Action
  • Catch Pokémon (for wild battles9
  • Use Struggle (regardless of the Pokémons PP)
  • Giving up
  • Ending battle (just to stop in the middle of the battle)
  • Take no Action
About actions themselves in the battle:
  • Hit or miss of a move, down to specifically targeting a battler in a multi battle
  • Sucess for protecting moves
  • Damage amount
  • Ensuring HP of a battler
  • Triggering effects for moves, abillities and items
  • Critical hits
  • Flinching (for item and ability based flinching)
  • target of the action
  • Amount of hits for multiple hit moves, including which of these should be critical
  • Thawing of a Pokémon
  • Breaking through confusion, etc.
  • Duration of statuses
  • Actions that will be taken on mid-battle switching (U-Turn and alike)
  • Priority / When each battler should move
  • Make Pokémon Mega Evolve
  • Make Pokémon Ultra Burst*
  • Make Pokémon Dynamax*
  • Make Pokémon Gigantamax*
  • Make Pokémon disobey and also define in what way (take a nap, hit itself, etc.)
  • What to-do when a battler faints
  • Set a message right before a move is used successfully
  • Set a message right before a Pokémon tries to use a move
  • Set a message at the beginning of the round
  • For all message option above: If the trainer should be slided in and out
  • Set a custom message on battle end (usefull for giving up, to provide a custom reason)
  • Internal result of the battle
  • Wheter a Pokémon will be captured successfully, down to the amount of shakes
  • If a Pokéball is to be treated as a snag ball (use only on last Pokémon)


How to install

There are two ways you can install this script. An easy and a clean way. I always recommend the clean, if you want to stick with the script, as it is more organized and easier to provide help. If you just want to test it first, you can use the easy method.

1) In both cases download the zip file.

2 a) For easy setup: Copy all the contents of the three text files in a new script section above main and use the file name as the name for the script section. The proper order is indicated by the numbers at the beginning of the file name.

2 b) For clean setup: Copy the contents of each .txt file, that is in the clean folder, in a new script section above main. Make sure that "Scripted_Battle_Compile" is the last section before main. The proper order is indicated by the numbers at the beginning of the file name.

3) In the Compiler script section (the one from Essentials), right after
Ruby:
Expand Collapse Copy
if !$INEDITOR && LANGUAGES.length>=2
  pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
end
add
Ruby:
Expand Collapse Copy
# Compile scripted battles
  pbCompileScriptedBattles(mustCompile)

4) Create a folder called "battles" in your projects PBS folder. This is where all your raw battle scripts will be stored.

5) Now you can start writing your battles. You find examples in the examples folder. Note that you might need to add some of the trainers to your PBS file. Just copy the following and add it to your trainers.txt.

Optional: Download and install the ZUD Plugin for additional features.

#-------------------------------
[POKEMONTRAINER_Red, Red]
LoseText = "..."
Pokemon = SERPERIOR,50
Item = LEFTOVERS
Name = Sevi
Pokemon = TENTACRUEL,50
Item = BLACKSLUDGE
Pokemon = DUSCLOPS,50
Ability = 0
Pokemon = CHANSEY,50
Pokemon = SYLVEON,50
Item = LEFTOVERS
Pokemon = METAGROSS,50
Item = METAGROSSITE
#-------------------------------
[POKEMONTRAINER_Leaf, Leaf]
LoseText = "..."
Pokemon = TENTACRUEL,50
Item = BLACKSLUDGE
Pokemon = LAPRAS,50
Pokemon = SEISMITOAD,50
Item = LEFTOVERS
Pokemon = BLASTOISE,50
Item = BLASTOISINITE
Pokemon = SHARPEDO,50
Ability = 2
Item = ROCKYHELMET
Pokemon = DRAGONITE,50

How to use

Once setup, create a new file of type .rb or .txt in the PBS/battles folder. In here you write your battle as regular Ruby code (same as in RMXP). I highly recommend using .rb files and a at least somewhat professional code editor. VSCode does the trick and also gives you add ons for checking and formatting your code.

When you set up everything up, run your game in Debug mode and the script will be compiled. If you get errors, you probably have an error somewhere in your script. Go and check for that. The lines that are shown on the error message are dependent on the amount of blank lines or comments you have. Meaning the more of those you have, the great the difference will be. It still helps to get at least somewhere around the right position. Again, a professional code editor really helps with finding these right away.

To start a battle, call the battle by its filename, without the extension. So if your battle is named "redVSblue.rb" you just call pbScriptedTrainerBattle("redVSblue").

All details for how to use scripted and simulated battles can be found in the doc files "Simulated_Battle_Docs.txt" and "Scripted_Battle_Docs.txt" respectively.


Unsure of how easy or hard it is to write a cusom battle?
Ruby:
Expand Collapse Copy
# This battle is a recreation of the battle sharkeatyoshi vs. SELENA
# The original can be found here: https://www.youtube.com/watch?v=0N2BxiEbFO0
# I had to give Klefki a hidden ability, cause Prankster made Tyranitar mis
# You know, Gen 7 things :D

# -------- Trainers ------------------------------------
RED = Scripted_Trainer.new(:POKEMONTRAINER_Red,"Red")
LEAF = Scripted_Trainer.new(:POKEMONTRAINER_Leaf,"Leaf")

# -------- RED Party -----------------------------------
ARCANINE = pbNewPkmn(:ARCANINE,50,RED)
ARCANINE.setAbility(0)
ARCANINE.setItem(:SAFETYGOGGLES)

STEELIX        = pbNewPkmn(:STEELIX,50,RED)
STEELIX.setItem(:STEELIXITE)

TYRANITAR     = pbNewPkmn(:TYRANITAR,50,RED)

CRESSELIA     = pbNewPkmn(:CRESSELIA,50,RED)
CRESSELIA.setItem(:SITRUSBERRY)

RED_PARTY     = [ARCANINE,TYRANITAR,CRESSELIA,STEELIX]
RED.setParty(RED_PARTY)


# -------- LEAF Party ---------------------------------
LOPUNNY        = pbNewPkmn(:LOPUNNY,50,LEAF)
LOPUNNY.setItem(:LOPUNNITE)
LOPUNNY.makeShiny

JUMPLUFF    = pbNewPkmn(:JUMPLUFF,50,LEAF)
JUMPLUFF.setItem(:LEFTOVERS)
JUMPLUFF.makeShiny

KLEFKI        = pbNewPkmn(:KLEFKI,50,LEAF)
KLEFKI.setItem(:AIRBALLOON)
KLEFKI.setAbility(2)

VIVILLON    = pbNewPkmn(:VIVILLON,50,LEAF)
VIVILLON.form = 13

LEAF_PARTY    = [KLEFKI,JUMPLUFF,VIVILLON,LOPUNNY]
LEAF.setParty(LEAF_PARTY)

# -------- Battle -------------------------------------
battle = {
    "round1" => {
    RED => [
        [
            :UseMove,
            ARCANINE,
            :HEATWAVE,
            {
                :effect => true,
                :damage => [JUMPLUFF,"30%r",KLEFKI,"87%"],
                :priority => 2,
                :moveMessage => "Arcanine wants to impress Red!",
            }
        ],
        [
            :UseMove,
            TYRANITAR,
            :ROCKSLIDE,
            {
                :effect => true,
                :damage => "100%",
                :breakThroughStatus => false,
                :priority => 1,
            }
        ]


    ],
    LEAF => [
        [
            :UseMove,
            KLEFKI,
            :THUNDERWAVE,
            {
                :target => TYRANITAR,
                :priority => 4
            }
        ],
        [
            :UseMove,
            JUMPLUFF,
            :SLEEPPOWDER,
            {
                :target => ARCANINE,
                :priority => 3
  
            }
        ]
    ]
  },
  #------------------------
  "round2" => {
    RED => [
        [
            :UseMove,
            ARCANINE,
            :HEATWAVE,
            {
                :breakThroughStatus => false,
                :priority => 2
            }
        ],
        [
            :UseMove,
            TYRANITAR,
            :ROCKSLIDE,
            {
                :effect => true,
                :breakThroughStatus => true,
                :priority => 1
            }
        ]
    ],
    LEAF => [
        [
            :UseMove,
            KLEFKI,
            :THUNDERWAVE,
            {
                :target => ARCANINE,
                :onFaint => [:SwitchTo,LOPUNNY],
                :priority => 4
            }
        ],
        [
            :UseMove,
            JUMPLUFF,
            :LEECHSEED,
            {
                :target => TYRANITAR,
                :onFaint => [:SwitchTo,VIVILLON],
                :priority => 3,
  
            }
        ]
    ]
  },
  #------------------------
  "round3" => {
    RED => [
        [
            :UseMove,
            ARCANINE,
            :WILLOWISP,
            {
                :target => LOPUNNY,
                :priority => 2,
                :tryUseMoveMessage => "Arcanine can't get it together!"
            }
        ],
        [
            :SwitchTo,
            TYRANITAR,
            CRESSELIA,
        ]
    ],
    LEAF => [
        [
            :UseMove,
            LOPUNNY,
            :FAKEOUT,
            {
                :target => ARCANINE,
                :damage => "24%",
                :makeMega => true,
                :priority => 4
            }
        ],
        [
            :UseMove,
            VIVILLON,
            :HURRICANE,
            {
                :target => TYRANITAR,
                :damage => "38%",
                :critical => true,
                :priority => 3
            }
        ]
    ]
  },
  #------------------------
  "round4" => {
    RED => [
        [
            :UseMove,
            ARCANINE,
            :HEATWAVE,
            {
                :breakThroughStatus => true,
                :damage => "100%",
                :priority => 1
            }
        ],
        [
            :UseMove,
            CRESSELIA,
            :PSYCHIC,
            {
                :target => LOPUNNY,
                :hit => false,
                :priority => 2
            }
        ]
    ],
    LEAF => [
        [
            :UseMove,
            LOPUNNY,
            :BOUNCE,
            {
                :target => CRESSELIA, # damage will be defined next turn
                :priority => 4
            }
        ],
        [
            :UseMove,
            VIVILLON,
            :HURRICANE,
            {
                :target => ARCANINE,
                :hit => false,
                :priority => 3
            }
        ]
    ]
  },
  #------------------------
  "round5" => {
    RED => [
        [
            :SwitchTo,
            ARCANINE,
            STEELIX
        ],
        [
            :UseMove,
            CRESSELIA,
            :TRICKROOM,
            {
                :priority => 3
            }
        ]
    ],
    LEAF => [
        [
            :UseMove,
            LOPUNNY,
            :TACKLE, # to show that the move itself doesn't matter / LOPUNNY will still use bounce
            {
                :target => CRESSELIA,
                :damage => "17%", # target should still be set
                :priority => 4
            }
        ]
    ]
  },
  #------------------------
  "round6" => {
    RED => [
        [
            :UseMove,
            STEELIX,
            :HEAVYSLAM,
            {
                :makeMega => true,
                :damage => "5%r",
                :priority => 4,
                :roundMessage => ["It's over Leaf! I have the high ground!",true]
            }
        ],
        [
            :UseMove,
            CRESSELIA,
            :PSYCHIC,
            {
                :priority => 4,
                :damage => "100%"
            }
        ]
    ],
    LEAF => [
        [
            :UseMove,
            LOPUNNY,
            :TACKLE,# doesn't matter, as it will faint before it can move
            {
                :target => CRESSELIA,
                :roundMessage => ["Well,...",true],
                :battleEndMessage => "Both battlers showed great sportsmanship!"
            }
        ]
    ]
  },
}


settings = {
    :size0 => 2,
    :size1 => 2
}
Scripted_Battle.new(RED,LEAF,battle,settings)

Known Bugs
BugSolutionStatus
When starting the game, I get the follwoing error:
Ruby:
Expand Collapse Copy
 undefined error in 2_Scripted_Trainer at line 14
Why this bug appears, is currently unknow. Use the following workaround for the time being:
In
Ruby:
Expand Collapse Copy
14_Scripted_Battle_Compile
right after
Ruby:
Expand Collapse Copy
def pbCompileScriptedBattles
add another "return". Start the game once and let everything else compile. Then close the game and remove the "return"
fixed in Version 2.1
Thanks to Rohit Yadav for helping me find the cause


For questions and bug reports visit our Discord channel https://discord.gg/7msDPaN or post them here.
Credits
Hollow_Ego
Maruno for all code that I copied and modified for this script
Lucidious89 and StCooler for the code that was used for compatibility with their ZUD plugin
Author
Hollow_Ego
Downloads
1,823
Views
4,083
First release
Last update

Ratings

5.00 star(s) 4 ratings

More resources from Hollow_Ego

Latest updates

  1. Bug fixes

    Fixed Bug, where end speeches wouldn't work on the player side in a simulated battle Fixed Bug...
  2. Bug Fix - Error on Line 14 in 2_Scripted_Trainer when compiling

    This new version contains a permanent solution to this bug, which was caused by my script trying...
  3. Major Update to support Z-Moves, Ultra Burst, Dynamx and GMax

    With this update you can now use Z-Moves, Ultra Burst, Dynamax and GMax in scripted battles. To...

Latest reviews

Hi, I get the following error :

Script 'Scripted_Battle_AI' line 1: TypeErrorOccurred.
undefined superclass 'PokeBattle_AI'

What can I do ?
Hollow_Ego
Hollow_Ego
Are you using Essentials Version 18 or higher? In earlier Version of Essentails there was no PokeBattle_AI class.
Man, I forgot to leave a review! So this is an incredible resource, it works perfectly, does a great job at simulating/ai battling down to the minuscule level without too much hassle (one would think something like this would be really complicated on the user-end), and Hollow was really supportive. I suggest you do the "clean" installation. Can't recommend enough.
Hollow_Ego
Hollow_Ego
Thanks for the review and the kind words :)

I'm glad you enjoy this resource and I'm looking forward to see how it will be used in a game.
Back
Top