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.
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
add
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.
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?
Known Bugs
For questions and bug reports visit our Discord channel https://discord.gg/7msDPaN or post them here.
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
- 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
- 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
- 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
- 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:
if !$INEDITOR && LANGUAGES.length>=2
pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
end
Ruby:
# 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
[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:
# 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
Bug | Solution | Status |
---|---|---|
When starting the game, I get the follwoing error:
Ruby:
| Why this bug appears, is currently unknow. Use the following workaround for the time being: In
Ruby:
Ruby:
| 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