Jump to content

Modding Tutorial (Reborn E19)


Haru,,

Recommended Posts

  • Developers

Adding a Pokemon

So. Let's start with the be-all end-all of Pokemon. Themselves.

 

Creating a Pokemon is quite easy, and by far the most common mod in the Mod Market. Let's break it down.

Pokemon in their default forms are found in the PBS folder inside pokemon.txt whereas their forms are found within MultipleForms.rb. The methods, things the game uses, that define a Pokemon are found within the file PokeBattle_Pokemon.rb and PokemonMultipleForms.rb.

 

Creating a New Pokemon

To start, open up pokemon.txt inside your workspace.

Next, we'll go ahead and copy the block of code for Bulbasaur:

Spoiler
[1]
Name=Bulbasaur
InternalName=BULBASAUR
Type1=GRASS
Type2=POISON
BaseStats=45,49,49,45,65,65
GenderRate=FemaleOneEighth
GrowthRate=Parabolic
BaseEXP=64
EffortPoints=0,0,0,0,1,0
Rareness=45
Happiness=70
Abilities=OVERGROW,CHLOROPHYLL
Moves=1,TACKLE,3,GROWL,7,LEECHSEED,9,VINEWHIP,13,POISONPOWDER,13,SLEEPPOWDER,15,TAKEDOWN,19,RAZORLEAF,21,SWEETSCENT,25,GROWTH,27,DOUBLEEDGE,31,WORRYSEED,33,SYNTHESIS,37,SEEDBOMB
EggMoves=AMNESIA,CHARM,CURSE,ENDURE,GIGADRAIN,GRASSWHISTLE,GRASSYTERRAIN,INGRAIN,LEAFSTORM,MAGICALLEAF,NATUREPOWER,PETALDANCE,POWERWHIP,SKULLBASH,SLUDGE
Compatibility=Monster,Grass
StepsToHatch=5355
Height=0.7
Weight=6.9
Color=Green
Habitat=Grassland
Kind=Seed
Pokedex=Bulbasaur can be seen napping in bright sunlight. There is a seed on its back. By soaking up the sun's rays, the seed grows progressively larger.
BattlerPlayerY=28
BattlerEnemyY=25
BattlerAltitude=0
Evolutions=IVYSAUR,Level,16

Then, you'll want to paste that all the way down at the end of the file, right after Eternatus. 

"Hey! Wait! Eternatus isn't in the game!" While that is true, its implementation actually is in the game, it just lacks sprites and is impossible to obtain. We decided it was easier to leave them in at the time of creation since Desolation, which was being developed for its latest release, and Rejuvenation, both had plans for Pokemon from the Galar Region. You can delete everything from after to Zeraora to Eternatus if you don't want a massive gap in your Pokedex.

 

Back to adding a new Pokemon....

Everything part of that Bulbasaur is what we're going to call a field. Each field is customizable. So, for our new Pokemon, let's use a fakemon called Beatote from the spriter Samson. You can find his old account on PokeCommunity, but almost all sprites have been taken down due to age. I took these straight out of ROM hacks of old that used them. 

 

The first things you'll need, of course, are a sprite, icon, and cry. I'll provide them for this Pokemon. You can find them here.

These must be named with their ID, which will be explained below. Take the image with just the number, and move that to Graphics/Battlers. Take the other image and drag that to Graphics/Icons. Finally, take the audio file and drag that to Audio/SE.

NOTE: If you delete the Galar Pokemon, you MUST rename these files to their new ID.

 

Secondly, you'll need to start editing the new Pokemon code you pasted.

  1. The first field, [1], should be changed to the next available ID.
  2. The second field, Name, is the display name.
  3. The third field, InternalName, is the name used in the code.
  4. Type1 is the primary typing. It can be any type defined in the code.
  5. Type2 is the secondary typing. 
  6. BaseStats are the Pokemon stats, of the order HP, Attack, Defense, Speed, Special Attack, Special Defense.
  7. GenderRate is what defines the gender ratio. The possible options are AlwaysMale, FemaleOneEighth, Female25Percent, Female50Percent, Female75Percent, FemaleSevenEighths, AlwaysFemale, and Genderless. 
  8. GrowthRate determines how fast the Pokemon levels up. The options are Medium or MediumFast, Erratic, Fluctuating, Parabolic or MediumSlow, Fast, and Slow. You can learn more about growth rates on any wiki website. 
  9. BaseEXP is the amount of EXP earned from defeating a Pokemon. It can be any whole number greater than zero.
  10. EffortPoints is the EV yield granted when defeated. It follows the same order as BaseStats. They can be any whole number greater than zero.
  11. Rareness is the catch rate. It can be any whole number between 0 and 255
  12. Happiness is the base friendship a Pokemon has. This typically is not changed from 70
  13. Abilities are the main abilities a Pokemon can have. They can be 1-2 abilities from any ability defined in PBS/abilities.txt
  14. HiddenAbility is the hidden ability. This feature is not present and simply a possible ability a Pokemon can have.
  15. Moves is the list of moves a Pokemon can learn by level up. They are formatted as a whole number, followed by the name of the move. 
  16. EggMoves is the list of moves a Pokemon can learn through breeding. 
  17. Compatibility is the Pokemon's egg group. The possible egg groups are: Monster Water1 Bug Flying Field Fairy Grass Humanlike Water3 Mineral Amorphous Water2 Ditto Dragon Undiscovered.
  18. StepsToHatch is the amount of steps require to hatch from an egg. Do not use any commas or decimals to indicate thousands, and it must be a whole number.
  19. Height can be any positive number. They use the American system of using decimal points.
  20. Weight can be any positive number. They use the American system of using decimal points.
  21. Color is typically the main color of the Pokemon. It's used solely by the Pokedex. It can be Red, Blue, Yellow, Green, Black, Brown, Purple, Gray, White, or Pink.
  22. Habitat is the cosmetic "location" a Pokemon can be found. This field can be ignored.
  23. Kind is the type listed in the Pokedex. This can be anything. 
  24. Pokedex is the Pokedex entry displayed in the Pokedex itself. This can be anything.
  25. WildItemCommon, WildItemUncommon, and WildItemRare make up the chance of holding an item, being 50%, 5%, and 1% respectively. If all three of these fields exist AND are the same item, the Pokemon will always spawn with that item. It can be any item defined in PBS/items.txt
  26. BattlerPlayerY and BattlerEnemyY can be left the same. They need to be any whole number. These can be adjusted to suit your needs to change the position.
  27. BattlerAltitude determines the height in battle. Should typically be left at 0. Can be any number greater or equal to 0. Shows a shadow if greater than zero.
  28. Evoltuions is what defines how the Pokemon can evolve. Evolutions have 3 parts: Pokemon, Evolution Method, and Evolution Parameter, in that order. A full list of evolution methods and their parameters can be found in PokemonEvolution.rb. We will discuss these later.

The premade data for Beatote can be found below:

Spoiler
[891]
Name=Beatote
InternalName=BEATOTE
Type1=BUG
Type2=GROUND
BaseStats=75,85,90,80,50,85
GenderRate=AlwaysMale
GrowthRate=Erratic
BaseEXP=184
EffortPoints=0,0,2,0,0,0
Rareness=45
Happiness=70
Abilities=ILLUMINATE,SWARM
HiddenAbility=PRANKSTER
Moves=1,FLASH,1,TACKLE,5,DOUBLETEAM,8,CONFUSERAY,12,QUICKATTACK,15,STRUGGLEBUG,19,MOONLIGHT,22,TAILGLOW,26,SIGNALBEAM,29,PROTECT,33,ZENHEADBUTT,36,HELPINGHAND,40,BUGBUZZ,43,PLAYROUGH,47,DOUBLEEDGE,50,INFESTATION
EggMoves=BATONPASS,BUGBUZZ,DIZZYPUNCH,ENCORE,LUNGE,SEISMICTOSS,SILVERWIND,TRICK
Compatibility=Bug,Humanlike
StepsToHatch=4080
Height=1.4
Weight=42.3
Color=Yellow
Kind=Groundfly
Pokedex=Beatote live underground, taking over the colonies of the Nincada that live in the area by blinding them.
WildItemUncommon=BRIGHTPOWDER 
BattlerPlayerY=23
BattlerEnemyY=19
BattlerAltitude=0
Evolutions=

 

So now we're done, right? Not so fast! Now that we've created a Pokemon, we need to compile. To compile, you want to

  1. Launch the game via the shortcut created earlier.
  2. Press F6 and type pbCompilePokemonData, then press enter.
  3. Alternatively:
    1. Open any save
    2. Pause the game, select Debug
    3. Scroll to "Compile All Data" and select it
  4. After either option, restart the game.

You'll pretty much want to do this any time you add new things to the game via the PBS.

Once you relaunch the game, you can give yourself your new Beatote via debug! Either go to the debug menu and hit Add Pokemon, or push F6 and enter the script:

pbAddPokemon(PBSpecies::BEATOTE,5)
Spoiler

image.png.842b7e11f1ab4868a8824af02fb1166d.png

 

  • Like 5
Link to comment
Share on other sites

  • Developers

Adding a Move

Probably the next big thing, moves. 

 

Moves are defined in PBS/moves.txt. They're a lot more complicated to set up, but quite fun to make. Let's break down the structure before we add any.

  1. The first field is the ID. They are typically in ascending order, but sometimes have gaps.
  2. The internal name is next. This is what you'll be using in the scripts and PBS files.
  3. The next field is the display name.
  4. The next field is the move function. I will explain this later.
  5. Next is the Base Power. 0 means no base power. 1 means custom power. Anything else is fair game.
  6. Typing. Any available type from PBS/types.txt
  7. Category. Physical/Special/Status. If defined as status, the base power MUST be zero. If defined as Physical/Special, the base power MUST be non zero.
  8. Accuracy. Number from 0 to 100. 0 never misses.
  9. Max PP. Any number. This number is before PP Ups. PP Ups are calculated automatically
  10. Effect chance. Percent chance for a secondary effect to trigger.
  11. Target Selection. Which Pokemon the move can target.
    Spoiler

    00 - Single Pokémon other than the user

    01 - No target (i.e. Counter, Metal Burst, Mirror Coat, Curse)

    02 - Single opposing Pokémon selected at random (i.e. Outrage, Petal Dance, Thrash, Uproar)

    04 - All opposing Pokémon

    08 - All Pokémon other than the user

    10 - User

    20 - Both sides (e.g. Sunny Day, Trick Room)

    40 - User's side (e.g. Light Screen, Mist)

    80 - Opposing side (i.e. Spikes, Toxic Spikes, Stealth Rocks)

    100 - User's partner (i.e. Helping Hand)

    200 - Single Pokémon on user's side (i.e. Acupressure)

    400 - Single opposing Pokémon (i.e. Me First)

    800 - Single opposing Pokémon directly opposite of user

     

  12. Move Priority. Used in determining turn order, values range from -6 to 6.
  13. Flags. By far the stupidest system of doing this but here we are. This includes aspects like sound, contact, high crit rate, etc. It can be any combination of letters a through n
    Spoiler

    a - The move makes physical contact with the target.

    b - The target can use Protect or Detect to protect itself from the move.

    c - The target can use Magic Coat to redirect the effect of the move. Use this flag if the move deals no damage but causes a negative effect on the target. (Flags c and d cannot both be used)

    d - The target can use Snatch to steal the effect of the move. Use this flag for most moves that target the user. (Flags c and d cannot both be used)

    e - The move can be copied by Mirror Move.

    f - The move has a 10% chance of making the opponent flinch if the user is holding a King's Rock/Razor Fang. Use this flag for all damaging moves that don't already have a flinching effect.

    g - If the user is frozen, the move will thaw it out before it is used.

    h - The move has a high critical hit rate.

    i - The move is a biting move (powered up by the ability Strong Jaw).

    j - The move is a punching move (powered up by the ability Iron Fist).

    k - The move is a sound-based move.

    l - The move is a powder-based move (Grass-type Pokémon are immune to them).

    m - The move is a pulse-based move (powered up by the ability Mega Launcher).

    n - The move is a bomb-based move (resisted by the ability Bulletproof).

  14. Description. Move description.

 

Now that we have these, we can create our own move. For an example, we'll be creating a move for our Beatote named "Bug Strike". It will have a high crit ratio, contact, get affected by protect, be affected by mirror move, flinch with king's rock, and have a chance to paralyze.

We can define that by:

772,BUGSTRIKE,Bug Strike,189,70,BUG,Physical,100,10,20,00,0,abef,"The user strikes the target with a tough appendage. Critical hits land more easily."

But wait! Function 189? What's that?

This is where the hard part comes in. We need to go to the file PokeBattle_MoveEffects.rb. This is where all of our move functions are defined. To make things simple, we will copy the code from Thunder. In case that file is not labeled with each move (You should definitely do this), you can find the function in PBS/moves.txt and search for it in PokeBattle_MoveEffects.rb.

At the end, the code should look like this:

# Bug Strike
class PokeBattle_Move_189 < PokeBattle_Move
  def pbAdditionalEffect(attacker,opponent)
    return false if !opponent.pbCanParalyze?(false)
    opponent.pbParalyze(attacker)
    @battle.pbDisplay(_INTL("{1} was paralyzed! It may be unable to move!",opponent.pbThis))
    return true
  end
end

Since we've defined a chance to proc an additional effect, we need to use the method pbAdditionalEffect. If we were to look at a status move or something like Superpower or Drain Punch, they use pbEffect. Moves like Thunder Fang with two effects require an additional method called pbSecondAdditionalEffect. If you were to want a move to have more than 2 additional effects with separate chances, you'd need to find where each of these methods are called in the game's scripts and add in new methods for that. Alternatively, you can add in a new random roll inside the effect. 

While you don't need to use pbAdditionalEffect and can just use pbEffect, it's better to stick with conventions and use them as intended.

 

Finally, to use the move, we need to give it to a Pokemon. We can simply add at the front of our Moves field in the Pokemon data "1,BUGSTRIKE"

An example of adding the move will be hidden below.

Spoiler
Moves=1,BUGSTRIKE,1,FLASH,1,TACKLE,5,DOUBLETEAM,8,CONFUSERAY,12,QUICKATTACK,15,STRUGGLEBUG,19,MOONLIGHT,22,TAILGLOW,26,SIGNALBEAM,29,PROTECT,33,ZENHEADBUTT,36,HELPINGHAND,40,BUGBUZZ,43,PLAYROUGH,47,DOUBLEEDGE,50,INFESTATION

 

After that, we can compile all!

 

Many types of effects are found within PokeBattle_MoveEffects.rb, such as Flying Press's multityped aspect, defining moves able to used while asleep, along with a lot more. The only thing that limits what you can do here is your own coding ability, understanding, and the small fact that you can only affect active battlers. 

  • Like 3
Link to comment
Share on other sites

  • Developers

Adding an Ability

Next up, abilities.

 

Abilities, as you'd expect, are defined in PBS/abilities.txt. They're very straightforward on the PBS end of things, only requiring an ID, Internal Name, Display Name, and Description. On the other hand, the entire implementation is code based. 

To fit in with Beatote's Pokedex entry of preying on Nincada, let's have its ability make its attack increase by 50% against Bug-type Pokemon.

 

To start, defining its ability in the PBS:

330,SCAVENGER,Scavenger,"Deal increased damage to Bug-type Pokémon."

 

Next, we'll give that ability to Beatote.

HiddenAbility=SCAVENGER

 

Now we can compile, and Beatote will now have the Scavenger ability!

Spoiler

image.png.b806cf28d60f4aadf40bc9d1538c758d.png

 

And now, we need to implement it!

There's a lot to do here, so bear with me and try to follow along. We want to head to the file PokeBattle_Move.rb. This file is where all damage calculation takes place, and where the magic mainly happens.

You'll want to head down to around line 1448, which is after all the field effect code. You'll be looking for a line that says:

case attacker.ability
when PBAbilities::GUTS

In here, we'll want to add a few lines so we end up with:

case attacker.ability
when PBAbilities::SCAVENGER
	atkmult=(atkmult*1.5).round if opponent.hasType?(:BUG)
when PBAbilities::GUTS

I'll explain what's going on here.

 

This is a method called pbCalcDamage. Inside of it, it takes three parameters in addition to an optional hitnum named parameter. While the parameters options and hitnum are inconsequential, attacker and opponent are what we really care about here. Both attacker and opponent will be PokeBattle_Battler objects, found inside PokeBattle_Battler.rb. Any method or attribute in there can be called and utilized for creating a damaging move.

The method hasType? takes a type and returns if the object has it or not.

 

pbCalcDamage is split into parts:

Spoiler
  1. Initialization, including exiting if base damage is 0, pulling base damage from PBS, etc.
  2. Calculate the base damage.
    1. Abilities, such as Sheer Force and Pixilate.
    2. Items, such as gems, plates, and legendary orbs (Griseous Orb, Soul Dew, etc)
    3. More effects conditionally, being Charge, Helping Hand, Mud/Water Sport, Kalos Legend Abilities, Knock Off, and Lunala Z vs Minimize.
    4. Field effect changes.
  3. Calculate the attacker's attack stat comes next, being the Pokemon using the move.
    1. Determine if physical or special.
    2. Adjust for Unaware/Hustle/Power Spot.
    3. More field effects.
    4. Conditional attack modifier abilities (Starters, Swarm).
    5. Attack modifier abilities (Scavenger, Huge Power, Guts, Flash Fire, etc).
    6. Item modifiers, such as Light Ball, Thick Club, Choice items
    7. Thick Fat must be done LAST.
  4. Calculate the corresponding defense stat.
    1. Same shtick applies here. Very repetitive.
  5. Calculate the effective, or actual, damage.
    1. Multihit moves 
    2. Generic field boosts, such as type matching.
    3. Primal Abilities return 0 damage here if nullified by respective weather.
    4. Field transformations, such as Crystal Cave > Dark Crystal Cave or Factory Field
    5. Sun/Rain
    6. Crit calculation
    7. Damage rolls
    8. STAB calculation
    9. Type effectiveness check
    10. Gem message + Burn/Water Bubble
    11. Effective damage mods, such as Screens, Multiscale, Friend Guard, Life Orb, Berries, etc.
  6. Calculate final damage using above methods.

 

Now your ability functions. But only for the player. The AI does not know what's actually going on with your ability, it simply sees nothing, We need to head to the file "PokeBattle_AI_2.rb".

This file is a wonder. It's incredibly complicated and I won't bore you trying to teach it. The gist is, you need to find similar functioning abilities and insert your new ability in. If you look at where we inserted Scavenger in the PokeBattle_Move.rb, we should look for spots where those abilities are and copy them, provided we ignore any field-specific effects for them. This will apply similar logic to before. I'll state which methods we'll be modifying. This part doesn't need to be done, but should if you plan on making the AI have a fair chance.

 

Certain abilities should be more weighted heavily in the first location, a method called getAbilityDisruptScore, which is the score the AI gets for whether or not it should "counter" the ability. We'll place this right near where the code for Huge Power is. The multiplier here is typically the same.

when PBAbilities::SCAVENGER
	abilityscore*=1.5 if opponent.hasType?(:BUG)

 

The next spot is where we calculate ability score for the AI to find the best switch for. It can be found by searching abilityscore in the file. It starts at around line 8035 on clean code.

Pretty much anywhere after the line case i.ability we will be adding the code:

when PBAbilities::SCAVENGER
	abilityscore+=30 if @opponent.hasType?(:BUG)

The amount to add here is pretty subjective. The general process is 10 for "hey this is better than no ability" or a much higher number for "hey this is a really freaking good idea do this."

However much you want to add for your own abilities is up to you.

 

The final spot where it's required is much further down labeled with a comment tag

############ ATTACKER ABILITY CHECKS ############

 

You can search for this to find it. We'll be adding this line into the code there. It can be anywhere after Technician but before Type Changing Abilities. Typically group like changes together.

#Scavenger
elsif attacker.ability == PBAbilities::SCAVENGER
	if opponent.hasType?(:BUG)
		atk=(atk*1.5).round
	end

 

Congrats! You've taken your first real step into full content mods with this! There's still a whole lot going on here behind the scenes, but I'm not going to explain it solely based on the fact it would take way too long to explain everything. I've explained the important stuff, much of it has labels, and much of it is very self-explanatory thanks to our wonderful developers (humblebrag). Let's hop into the next topic.

  • Like 3
Link to comment
Share on other sites

  • Developers

Evolutions

Now. I'm sure you've thought Beatote is familiar at this point. It's actually a fake evolution of Volbeat! For our evolution method, we will be having Volbeat need to know Tail Glow and be at least level 30. Let's code that in!

 

To start, we need to head to PokemonEvolution.rb

Our first step is to define a new evolution constant. These are what you'll see immediately into opening the file. At the end of that list, you'll want to this add the code. 

Beatote = 33

Feel free to make the spaces match.

 

Next, we'll want to add to the EVONAMES array. Just add a "Beatote" entry right after where it says "Custom7".

 

Finally, to finish the definition, we need to add to the EVOPARAM array. What each number means is defined right above it. All we want for that is an integer, which is to say another 1. Below is what the two arrays should look like:

Spoiler
EVONAMES=["Unknown",
  "Happiness","HappinessDay","HappinessNight","Level","Trade",
  "TradeItem","Item","AttackGreater","AtkDefEqual","DefenseGreater",
  "Silcoon","Cascoon","Ninjask","Shedinja","Beauty",
  "ItemMale","ItemFemale","DayHoldItem","NightHoldItem","HasMove",
  "HasInParty","LevelMale","LevelFemale","Location","TradeSpecies",
  "BadInfluence","Affection","LevelRain","LevelDay","LevelNight","Custom6","Custom7",
  "Beatote"
]

# 0 = no parameter
# 1 = Positive integer
# 2 = Item internal name
# 3 = Move internal name
# 4 = Species internal name
# 5 = Type internal name
EVOPARAM=[0,     # Unknown (do not use)
  0,0,0,1,0,     # Happiness, HappinessDay, HappinessNight, Level, Trade
  2,2,1,1,1,     # TradeItem, Item, AttackGreater, AtkDefEqual, DefenseGreater
  1,1,1,1,1,     # Silcoon, Cascoon, Ninjask, Shedinja, Beauty
  2,2,2,2,3,     # ItemMale, ItemFemale, DayHoldItem, NightHoldItem, HasMove
  4,1,1,1,4,     # HasInParty, LevelMale, LevelFemale, Location, TradeSpecies
  1,1,1,1,1,1,1, # Custom 1-7
  1              # Beatote
]

 

Now, to actually implement our evolution method, we need to head down to the method pbMiniCheckEvolution. The method takes in 4 parameters, being the Pokemon object, its evolution method, the parameter defined in PBS/pokemon.txt, and the species it evolves into. 

Following the structure shown in pbMiniCheckEvolution, we want to do the same for our new one, making sure our Pokemon is above the level and has the required move. That will look like this:

when PBEvolution::Beatote
	return poke if pokemon.level >= level && pokemon.knowsMove?(:TAILGLOW)

 

Lastly, we need to add the evolution method to Volbeat in PBS/pokemon.txt. It's very simple, all that needs to be done is filling out the evolution field in Volbeat's block. Reminder you can push Ctrl + F to search through a file.

Evolutions=BEATOTE,Beatote,30

 

After that, you can compile, and the evolution will work.

Spoiler

image.png.6b02d986fa9114af16279d7a96413606.png

 

  • Like 3
Link to comment
Share on other sites

  • Developers

Adding a Type

This one's easy. Unfortunately, it's also incredibly broken. You'll need to download this file to make the type compiler work. Our bad.

Anyway. Light Type. Simple and quick. On brand to a Volbeat line. 

 

Heading over to PBS/types.txt,we see a few parameters, being:

  • Name
  • InternalName
  • IsSpecialType, which decides if a type is physical or special on Glitch field
  • Weaknesses, which types it is weak to
  • Resistances, which types it resists
  • Immunities, which types it is immune to

We can pretty much throw anything at it. Here's what I did

[19]
Name=Light
InternalName=LIGHT
IsSpecialType=true
Weaknesses=DARK,NORMAL
Resistances=BUG,ELECTRIC,LIGHT
Immunities=FIRE

Additionally, I added Light to Dark's Weakness field to make them weak to each other.

 

Then we'll go ahead and replace Beatote's Ground typing with Light in PBS/pokemon.txt, and then compile. The last thing we need is an image for the type. I'll provide that, and it needs to replace the one in Graphics/Pictures. You'll need an editor such as paint.NET if you want to do it yourself.

Spoiler

image.png.0953b652c78492f11039d8d87db6f400.png

 

And there's a new type! Probably the easiest thing so far. 

There are other graphics where a light type might need its own image, such as in the field notes or in battle. Those are in Graphics/Icons and Graphics/Pictures/Battle respectively.

  • Like 3
Link to comment
Share on other sites

  • Developers

Adding Items

We'll add 2 different items here. A new TM, and a new battle item. 

Items are defined in PBS/items.txt and TM compatibility is stored in PBS/tm.txt. We'll cover tm.txt later, so let's focus on items.txt for now.

 

The format for items is comprised of:

  1. ID
  2. Internal Name
  3. Display Name
  4. Item Pocket (Items, Medicine, Poke Balls, TMs, Berries, Crystals, Battle Items, Key Items, being represented by a number 0 through 7 in order)
  5. Item Price
  6. Item Description
  7. Item Use From Bag
    Spoiler

    0 - No use

    1 - One time use with party screen (Potions)

    2 - One time use (Repel, Escape Rope)

    3 - TMs

    4 - TMX (HMs)

    5 - Multi-use party screen (Legendary items, Flutes)

     

  8. Item Use In Battle
    Spoiler

    0 - No use

    1 - Single use (Potions, Elixirs)

    2 - Single use without target (X Items, PokeBalls, PokeDoll)

    3 - Flutes

     

  9. Item Type
    Spoiler

    0 - Other

    1 - Mail (Unused)

    2 - Mail

    3 - Snag Ball (Unused)

    4 - Poke Ball

    5 - Berry

    6 - Key Item

    7 - Z Crystal (bag item)

    8 - Z Crystal (held item)

     

  10. TM Move if applicable

For a TM, let's create a TM for Megahorn. To do this, we need to first search through the list of items and find the last created TM. In our case, that would be TM101. Then, we head down to the end of and get our next ID, giving us:

874,TM101,TM101,4,7500,"Using a tough and impressive horn, the user rams into the target with no letup.",3,0,0,MEGAHORN

 

After that, we need to head to PBS/tm.txt. There, we can use the format shown to add the compatibility.

[INTERNALNAME]
POKEMON,POKEMON,...

 

We'll then compile and have a new working TM!

Spoiler

image.png

 

Now, for our battle item. This item will reset all negative stat changes. Seems simple enough, no? 

First, our icon:

item875.png.ccf6b0456e07c9bce8f795c5fdcd6bc3.png

Next, we'll go create an entry in the text file for our item:

875,XRESET,X Reset,7,500,"Removes all negative stat changes.",0,2,0

Then we can compile, and the item exists. But we still need to code its function. Here comes the doozy of a file named PokemonItemEffects.rb.

In here we have our ItemHandlers. We're going to want to head down to where it's labeled BattleUseOnBattler, which is where flag 2 of field 8 has all its items.

To know what to do here requires decent knowledge of each method available to a battler, item, and scene. In short, a battler has every attribute and method listed in PokeBattle_Battler.rb, an item is the item ID, and the scene will let you print messages in battle.

Our code should look something like this:

Spoiler
ItemHandlers::BattleUseOnBattler.add(:XRESET,lambda{|item,battler,scene|
   playername=battler.battle.pbPlayer.name
   itemname=PBItems.getName(item)
   scene.pbDisplay(_INTL("{1} used the {2}.",playername,itemname))
   reducedstats=false
   for i in 1..7
     if battler.stages[i]<0
      battler.stages[i]=0; reducedstats=true
     end
   end
   if reducedstats
     scene.pbDisplay(_INTL("{1}'s negative stats were reset!",battler.name))
     return true
   end
   scene.pbDisplay(_INTL("But it had no effect!"))
   return false
})

 

To explain a little further what's going on here:

  1. We access the Trainer name through the battler's battle accessor, through the pbPlayer method, and then accessing the name flag of the Player. Which, if you took a second to look at any other code, is very stupid. This will be fixed in the next game update.
  2. Get the item name 
  3. Print a use message using _INTL. You can mark variables using curly brackets and numbers. {1} means it will pull the first variable enclosed in the given arguments. _INTL is what most display text uses, and runs through a text formatter.
  4. We copy the code from White Herb elsewhere in the code. Essentially, we check every stat that is not HP to see if it has been reduced, if so, we toggle a flag and reset it.
  5. If the flag has been switched on, we confirm use. If not, we deny use.

Explanation aside, we can now compile for another working item! ItemHandlers are how items are coded functionally. Looking through a few examples like Poke Balls and Potions will help give a better understanding, Certain items, like Poke Balls, utilize shortcuts to account for every type of ball to generalize them. Those Poke Ball catch rates are handled during the battle. Others, such as Evolution Stone items, copy the handler for one item on to every other one of its type.

Spoiler

image.png

 

  • Like 3
Link to comment
Share on other sites

  • Developers

Modifying Encounters

These explanations will start to get shorter as there is less and less to cover. 

In PBS/encounters.txt, there exists a section for every map with valid encounters. Unfortunately, there is no way to modify what maps have encounters and what tiles are encounter tiles without the use of RPG Maker XP. I will never advocate for buying this unfortunate piece of software, but the things talented people can do will never cease to amaze me.

Back to encounters, they are very simply formatted.

  1. Map ID
  2. Land Encounter Rate, Cave Encounter Rate, Water Encounter Rate. This line is optional, and defaults to 25,10,10. These are divided by 180 for encounter rate.
  3. Encounter Type
    1. List of Pokemon, Min Level, Max Level, matching to the amount of encounters defined in PokemonEncounters.rb

The valid encounter types are:

Spoiler

Land

Cave (Cannot exist with any Land encounters or Bug Contest

Water

RockSmash

OldRod

GoodRod

SuperRod
HeadbuttLow
HeadbuttHigh
LandMorning
LandDay
LandNight
BugContest

 

While you can't add encounter types without RMXP, you CAN edit the available slots you can have. By default, you can only have slots as listed by the array EnctypeChance. You can modify these entries to allow for more than the given amount. Be warned, that you may encounter issues on places that don't have the new number you set them to, as each slot must be filled. Each sub array of EnctypeChance is based in percentages.

EnctypeDensities stores the default values for encounter rate. You can ignore this. And I'm honestly not too sure what EnctypeCompileDens is for if I'm being honest. These are all fairly old as far as I'm aware and there's little need to touch any of it.

 

The same process as before applies to changing encounters. Replace a Pokemon, change their possible levels, compile, and test!

  • Like 3
Link to comment
Share on other sites

  • Developers

Forms

Forms are a complete mess and I apologize to any modders out there who deal with them. As the one who rewrote them for Desolation, I feel your pain. 

Sob story aside, they are quite easy to implement! The file we need is MultipleForms.rb.

 

While I don't have an example for this one, I'll more accurately go into how they work.

First, there's a small array at the top called FormCopy. This array contains smaller arrays of [Base, Clone] to save repetition. It'll take anything listed in the Base and copy it over to the Clone.

Second, the actual meat of forms.

Rather than array, this uses a hash and symbols, something the current Reborn is almost switched over to. Ruby was built to use them, so we are.

Each entry is called a key, and they are using the ID number of each Pokemon listed. Each key stores another value, in this case being a hash with different keys inside of it. These new level of keys are: :FormName, :OnCreation, :MegaForm, :PulseForm, :DefaultForm, :UltraForm, and the string of any form name to pull data from.

  • :FormName contains keys, corresponding to form number, which return a form name
  • :OnCreation is a proc{} block that is used when generating encounters to check what form it should generate. Examples include Unown generating randomly and Rattata generating Alolan/Kantonian based on the map.
  • :MegaForm, :PulseForm, :DefaultForm, :UltraForm all correspond to their namesake form and return the specific form ID. Exclusions are Mewtwo and Charizard, who have 2 separate forms.
  • Each form name has its own hash tied to it, with keys overriding the base Pokemon's traits
    • Dex Entry, Type 1, Type 2, Base Stats, Ability, Movelist, Egg Moves, Height, Weight, Evolution, Wild Held Items, Catch Rate, and EV Yield

There is even further room for customization if you want to put the effort in, but I do not recommend it.

 

And that's everything directly related to Pokemon covered! 

You did it! Woohoo!

  • Like 3
Link to comment
Share on other sites

  • Developers

Afterword

Very useful and very powerful commands I have not explained are the puts and print commands. Puts will print out messages to the console you have opened in the background. Print will pop up and pause the game with a message window. If anything you code ever doesn't work, litter these all across your code to see what went wrong. You can use them to show variables at certain times in the code or just to label where in the code you are so you know what's not getting run. I know I use them literally all the time. I know the other devs that work with us do too. There should still be some littered about the code. 

 

If you understood anything that was said throughout this whole thing, congrats! You've got it in you to make some really freakin cool mods. If not, don't sweat it! Maybe coding isn't for you. Maybe you're an artist. Maybe you're the ideas person! Maybe you just need to read this through one last time to really digest it. Ctrl + Shift + F is one of your best friends in VSC.

 

Tutorials like these were what got me into Minecraft modding. Applying those skills towards Rejuvenation got me into making my first mod, the original Randomizer. That got me to the Challenge Pack (what a mess it was), and then on to the dev team for the Rebornian games. Now I'm creating a guide for you all. What I've shown you is by no means the limit. Look at Moto's mods. Look at my other mods. Look at the SWM Modular Modpacks. Look at AllGen. The possibilities are countless. It just takes time to understand what you can do. Please don't get too frustrated at not being able to do something. Calmly think it through. Brainstorm what you want to do, then try to find places in the code where you think you accomplish it. Copy pasting is your friend.

 

It's back to the dungeon for me though, I have other projects to work on.

 

Happy modding and lots of love~

Haru~

  • Like 5
Link to comment
Share on other sites

  • 2 months later...

Thank you so much for the tutorial! Really appreciate the time and effort you took to make this! I'm super new to all of this and it's been so helpful and educational! If you don't mind, I was wondering if you teach us how to add custom regional forms to the sprite sheet(especially if there's already another form like with megas) please? I tried searching for tutorials on how to do it but I could only find them for previous verions of the game from back when the sprites were still seperate.  

Link to comment
Share on other sites

  • Developers
On 8/8/2023 at 2:39 AM, suzume said:

Thank you so much for the tutorial! Really appreciate the time and effort you took to make this! I'm super new to all of this and it's been so helpful and educational! If you don't mind, I was wondering if you teach us how to add custom regional forms to the sprite sheet(especially if there's already another form like with megas) please? I tried searching for tutorials on how to do it but I could only find them for previous verions of the game from back when the sprites were still seperate.  

It's super easy. The file is arranged so that each Pokemon occupies a 192x192 square, with the backsprite being below it and the shinies being to the right. While it does require some know-how of working with art programs, and I recommend paint.NET or Piskel, all you're really doing is hitting the program-equivalent "Canvas Size..." button and increasing that value by 192 then placing in your sprites.

 

On the topic of, say, Galarian Slowpoke and Slowbro, our standard has largely been to just shift the Mega Form down 384 pixels and place the Galarian form between them, so as to prevent issues arising with evolutions pulling the wrong graphic. This does require the addition of changing Mega Slowpoke's form value to 2 instead of 1, but there should be a self explanatory field in the file for forms. 

While you don't particularly need to shift around existing forms, it does make the sprite sheet look like it has less "empty space," even though it's not much of a difference either way.

 

Sometimes, however, you'll have a sprite that exceeds the bounds of the 192x192 square. As of current Reborn E19, I believe these cases are handled specifically in the various bitmap methods (very easily findable looking for mentions of Exeggutor, Necrozma, Guzzlord, etc). You'll need to add your own exception to that list as well and properly label the sprite in the files in 4 separate images when applicable (For a Bulbasaur: "001_1.png", "001b_1.png", "001s_1.png", "001sb_1.png"). You'll also need a similar extra file when dealing with gender differences as well, simply adding an "_f" before the file extension. While thinking about it, I'm not exactly sure how a sprite that is too big would be handled with gender differences. Oh well.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 8/9/2023 at 5:23 PM, Haru,, said:

It's super easy. The file is arranged so that each Pokemon occupies a 192x192 square, with the backsprite being below it and the shinies being to the right. While it does require some know-how of working with art programs, and I recommend paint.NET or Piskel, all you're really doing is hitting the program-equivalent "Canvas Size..." button and increasing that value by 192 then placing in your sprites.

 

On the topic of, say, Galarian Slowpoke and Slowbro, our standard has largely been to just shift the Mega Form down 384 pixels and place the Galarian form between them, so as to prevent issues arising with evolutions pulling the wrong graphic. This does require the addition of changing Mega Slowpoke's form value to 2 instead of 1, but there should be a self explanatory field in the file for forms. 

While you don't particularly need to shift around existing forms, it does make the sprite sheet look like it has less "empty space," even though it's not much of a difference either way.

 

Sometimes, however, you'll have a sprite that exceeds the bounds of the 192x192 square. As of current Reborn E19, I believe these cases are handled specifically in the various bitmap methods (very easily findable looking for mentions of Exeggutor, Necrozma, Guzzlord, etc). You'll need to add your own exception to that list as well and properly label the sprite in the files in 4 separate images when applicable (For a Bulbasaur: "001_1.png", "001b_1.png", "001s_1.png", "001sb_1.png"). You'll also need a similar extra file when dealing with gender differences as well, simply adding an "_f" before the file extension. While thinking about it, I'm not exactly sure how a sprite that is too big would be handled with gender differences. Oh well.

I managed to do it! Thank you so much! 

If you don't mind me asking another question, how do you get mega stones working in the game? I followed your guide and managed to get the item in the game but I'm kind of lost as to where to code its function. 

Link to comment
Share on other sites

20 hours ago, suzume said:

I managed to do it! Thank you so much! 

If you don't mind me asking another question, how do you get mega stones working in the game? I followed your guide and managed to get the item in the game but I'm kind of lost as to where to code its function. 

Never mind, I figured it out! For anyone who's curious I was trying to give a custom regional variant a mega form. I got it working after adding the custom mega stone in PBStuff.rb. 
Thank you again to @Haru,, for your help, I really do appreciate it! 

  • Like 1
Link to comment
Share on other sites

On 8/15/2023 at 1:29 AM, CorruptedJ98 said:

I Know This Probably Wont Get seen but i need help with trying to make an ability like blaze that fuctions for dragon and fairy type moves but i cant figure it out plz help.

I've had trouble with making abilities at first too, so far it seems that all (or almost all) functionality of abilities is done in the scripts that start with "PokeBattle", just go through all of them and search for abilities that work similarly (like Blaze, which you mentioned), and then copy, paste and edit

I wish I could've explained it better, but other than that you just have to understand or at least guess (which I am doing ahah) what the code means and which part does what, etc., which I can't really explain to you (since I don't understand it myself and just do what I found out through trial and error)

Anyway, hope that helps!

Link to comment
Share on other sites

  • 3 weeks later...
  • 2 weeks later...
  • Developers
On 9/5/2023 at 12:02 PM, JacobBasque said:

I've been trying to add hydrabond from all gen reborn to my custom mega hydreigon  but when I go to click an attack I get this message I checked where it says the error is but there doesn't seem to be any error only in game

Screenshot (18).png

You'll need to actually define the move inside the effects code. You didn't properly get all the code from All Gen. You'll be easily able to find everything by just searching through the code for PBEffects::HydraBond

  • Thanks 1
Link to comment
Share on other sites

  • Developers
On 8/18/2023 at 7:34 PM, BeautifulSinner said:

Hi I have been trying to add a mon into reatomized and i keep getting this error pop up Everytime I try to debug the Mon into the game 

 

IMG_4661.jpeg

It's difficult to tell what exactly is going here. I very recommend not having your game stored in your computer's Temp directory in the first place. From the looks of it, something broke during compilation.

Link to comment
Share on other sites

  • 2 weeks later...
  • 3 weeks later...

So I have been trying to add a custom forme along with a mega evolution for that form. I successfully implemented the form in MultipleForms.rb, tested them out using debug mode, but whenever I mega evolve them in battle and exit, attempting to open my party or get into another battle with it gives me a big error message:

image.png.8d340165d70f5ad888af93273601b6c2.png

looking at the console gives me this error message:

image.png.7bd43a00a8e72e588458641bc174ee8e.png

I thought it had something to do with the spritesheet I created, but after re-doing it many times over, including the icons, I still have no dice.

Here is my spritesheet:

image.thumb.png.9640a6a7a7f851fd7b894770e7bb05eb.png

Here are the icons I used:

image.png.f37abd085295b7d83c2c1417ec693ee8.png

and here is the form set up in MultipleForms.rb:

image.thumb.png.cf30b3015072c73d2b4de26cf85c83f5.png

I have tried getting help on the Discord, but I haven't been able to receive any help there, so I am hoping I can get help here. Thank you for any help you can give me.

Link to comment
Share on other sites

@bihh3024 The cause of the error is the fact that you've made :DefaultForm correspond to a hash (as in :DefaultForm => {PBItems::MANECTITE => 0}) instead of an integer (as in :DefaultForm => 0). If you want to use a hash for the DefaultForm, you'll have to modify the "makeUnmega" function in the PokemonMultipleForms.rb script

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...