- Pokémon Essentials Version
- v20.1 ➖
You may already be aware of the formula used to calculate a Pokémon's experience yield. (If you're not, Buttjuice has a post on it here) This formula takes out the guesswork, but there's still some busywork by punching in the formula over and over for new Pokémon - so I made a script to leave that all up to the game.
Please note that this script is probably not going to be a simple plug-and-play - you'll have to follow the instructions (and possibly make further changes) depending on what suits your needs.
Paste in a new script section above Main.
The formula starts with the base stat total, then multiplies it by...
This is only designed to be used in a game where Pokémon can evolve twice at most. (Of course, if your game includes four-stage evolutionary lines, you'll already have to rework the formula to allow for a fourth-stage Pokémon. You're still welcome to use this code as a base if you'd like.)
A Pokémon is considered legendary if it has no evos or prevos and is in the Undiscovered Egg Group. You'll notice that this definition isn't quite 1:1 with Pokémon standards for legendary Pokémon. Urshifu evolves from Kubfu, though both are in the Undiscovered Egg Group. (Though Kubfu is actually treated as a normal first-stage mon for the sake of Exp yield) Unown has no evos/prevos and is in the Undiscovered Egg Group, but is not considered a legendary. I ultimately decided to do the simplest option that would be most accurate to canon rather than implement every exception to the rule at once.
To change this, look at this code block here -
SOLO_MULT is the same as SECOND_STAGE_MULT, and LEGENDARY_MULT is the same as THIRD_STAGE_MULT. I just included both to make the reasoning a little more clear. (And also in the event anyone wants to toy around with exp yield through the base exp of Pokémon.) BONUS_MULT is multiplied with the existing mult to increase it - it's used for the Happiny family and Audino, to get their boosted yields. (It's off by about a point, though)
I tried to arrange it so that it would be pretty intuitive to try to add another condition. For example, Volcarona is treated as a legendary, so that means its multiplier should be set to the LEGENDARY mult -
Or suppose I want to include Lucidious' Legendary Breeding - I might make a species flag "Legendary", and check for that instead of checking for the Undiscovered egg group.
You've got a few options here, each with their own pros and cons.
Simplest to implement, just add in this code -
The game won't even look at the BaseExp value in the PBS, and will just use this formula when calculating exp. However, it won't reflect this in in the PBS or in any debug editors. (If your players are ever curious about the exp yield of a species - not common, but might be relevant if you plan on making a wiki - you'll need to make it clear the values in the PBS are not necessarily accurate.) It will apply this to all species, so any exceptions to the rules will need to be coded in that section mentioned earlier.
The same code, but with an extra conditional that might yield the
In this example, the game would normally check the
This one's a little trickier because it involves changing the base scripts and then reverting your changes. However, I personally prefer it because the values are now written out in a document you can edit - not only can you see them for yourself (as can your players, if you leave the PBS in), but you also have more of a baseline to edit them if you want to add more exceptions. For example, if you have a Pokémon with a hindering ability like Slaking or Regigigas, you'd have a starting point for the exp yield, and could decide how much to lower it from there.
In Compiler_WritePBS, press Ctrl+H and run a search that finds base_exp and replaces it with calculated_exp, like so:
Now run your game in Debug mode and go to Debug menu->Other Options->Create PBS File(s). Create pokemon.txt and pokemon_forms.txt. The game will rewrite these files using this formula. (All other data will be kept the same)
Close out of the game, do another Ctrl+H to undo the first -
And start your game again to compile any changes.
This does have one major setback, though - it's not going to automatically update. If you add another Pokémon, you'd have to do this process all over again. (And overwrite any exceptions in the process) It's best done when all your Pokémon are implemented - and if you're already using placeholder values, you may find it easier to just take Option 2.
Please note that this script is probably not going to be a simple plug-and-play - you'll have to follow the instructions (and possibly make further changes) depending on what suits your needs.
Code
Paste in a new script section above Main.
Ruby:
module GameData
class Species
FIRST_STAGE_MULT = 4.0
SECOND_STAGE_MULT = 7.0
THIRD_STAGE_MULT = 9.0
SOLO_MULT = 7.0
LEGENDARY_MULT = 9.0
BONUS_MULT = 2.5
def evo_stage_array
base = get_baby_species
ret = [base]
unless base==species
base_data = GameData::Species.get(base)
base_data.get_evolutions(true).each do |evo| # [new_species, method, parameter, boolean]
ret.push(evo[0]) if evo[0] == species || evo[0] == get_previous_species
end
end
unless ret[1]==species || !ret[1]
stage1_data = GameData::Species.get(ret[1])
stage1_data.get_evolutions(true).each do |evo| # [new_species, method, parameter, boolean]
ret.push(evo[0]) if evo[0] == species || evo[0] == get_previous_species
end
end
get_evolutions(true).each do |evo| # [new_species, method, parameter, boolean]
unless evo[3]
ret.push(evo[0])
break
end
end
ret.push(species) if !ret.include?(species) #Prevents issues with Pokemon where method is None
return ret
end
def calculated_exp
array = evo_stage_array
bst = base_stat_total.to_f
stage = array.index(species)
mult = [FIRST_STAGE_MULT,SECOND_STAGE_MULT,THIRD_STAGE_MULT][stage]
mult = SOLO_MULT if array.length == 1
mult = LEGENDARY_MULT if array.length == 1 && egg_groups.include?(:Undiscovered)
mult *= BONUS_MULT if [:HAPPINY,:CHANSEY,:BLISSEY,:AUDINO].include?(species)
ret = ((bst * mult)/20.0).round.to_i
return ret
end
end
end
Mechanics
The formula starts with the base stat total, then multiplies it by...- 4 if it's the first in an evolutionary line
- 7 if it's the second in an evolutionary line, or if it's not part of an evolutionary line
- 9 if it's the third in an an evolutionary line, or if it's a legendary
This is only designed to be used in a game where Pokémon can evolve twice at most. (Of course, if your game includes four-stage evolutionary lines, you'll already have to rework the formula to allow for a fourth-stage Pokémon. You're still welcome to use this code as a base if you'd like.)
A Pokémon is considered legendary if it has no evos or prevos and is in the Undiscovered Egg Group. You'll notice that this definition isn't quite 1:1 with Pokémon standards for legendary Pokémon. Urshifu evolves from Kubfu, though both are in the Undiscovered Egg Group. (Though Kubfu is actually treated as a normal first-stage mon for the sake of Exp yield) Unown has no evos/prevos and is in the Undiscovered Egg Group, but is not considered a legendary. I ultimately decided to do the simplest option that would be most accurate to canon rather than implement every exception to the rule at once.
To change this, look at this code block here -
Ruby:
mult = [FIRST_STAGE_MULT,SECOND_STAGE_MULT,THIRD_STAGE_MULT][stage]
mult = SOLO_MULT if array.length == 1
mult = LEGENDARY_MULT if array.length == 1 && egg_groups.include?(:Undiscovered)
mult *= BONUS_MULT if [:HAPPINY,:CHANSEY,:BLISSEY,:AUDINO].include?(species)
I tried to arrange it so that it would be pretty intuitive to try to add another condition. For example, Volcarona is treated as a legendary, so that means its multiplier should be set to the LEGENDARY mult -
Ruby:
mult = LEGENDARY_MULT if species==:VOLCARONA
Ruby:
mult = LEGENDARY_MULT if has_flag?("Legendary")
Using the Script
You've got a few options here, each with their own pros and cons.Option 1 - Scripted Values, No Exceptions
Simplest to implement, just add in this code -
Ruby:
class Pokemon
# @return [Integer] this Pokémon's base Experience value
def base_exp
return species_data.calculated_exp
end
end
Option 2 - Partially Scripted
The same code, but with an extra conditional that might yield the BaseExp
value instead.
Ruby:
class Pokemon
# @return [Integer] this Pokémon's base Experience value
def base_exp
if species_data.base_exp == 1
return species_data.calculated_exp
else
return species_data.base_exp
end
end
end
BaseExp
value in the PBS, but if that value was 1, it would use this formula to calculate exp yield instead. This can be useful if you're adding Fakemon to the canon PokéDex - you wouldn't have to worry about screwing up old values, but you could also just do BaseExp = 1
for all your Fakemon and save yourself a lot of hassle.Option 3 - Write to the PBS
This one's a little trickier because it involves changing the base scripts and then reverting your changes. However, I personally prefer it because the values are now written out in a document you can edit - not only can you see them for yourself (as can your players, if you leave the PBS in), but you also have more of a baseline to edit them if you want to add more exceptions. For example, if you have a Pokémon with a hindering ability like Slaking or Regigigas, you'd have a starting point for the exp yield, and could decide how much to lower it from there.In Compiler_WritePBS, press Ctrl+H and run a search that finds base_exp and replaces it with calculated_exp, like so:
Now run your game in Debug mode and go to Debug menu->Other Options->Create PBS File(s). Create pokemon.txt and pokemon_forms.txt. The game will rewrite these files using this formula. (All other data will be kept the same)
Close out of the game, do another Ctrl+H to undo the first -
And start your game again to compile any changes.
This does have one major setback, though - it's not going to automatically update. If you add another Pokémon, you'd have to do this process all over again. (And overwrite any exceptions in the process) It's best done when all your Pokémon are implemented - and if you're already using placeholder values, you may find it easier to just take Option 2.
Related
- Credits
- TechSkylander1518 for the code
Maruno, Buttjuice, and Cave of Dragonflies for sharing the formula