- 220
- Posts
- 13
- Years
- Seen Nov 29, 2021
How to add a third type:
WARNING: This tutorial will break anything that relies upon [PBEffects::Type3], which is used for moves that assign a third type. It's possible to make those moves function and have three-typed Pokemon, but that is beyond the scope of this tutorial.
Step 1: Assign a free byte to your third type. The numbers available for use should be listed in def pbCompilePokemonData under Complier. For this example we'll be using "X" (make sure to use an actual number for yours).
To do this, find where "Type2" is in pbCompilePokemonData (just scroll down a bit), and copy it. Then change the name from "Type2" to "Type3". Your code should look something like this:
Great, now we've established a data byte for our third type, on to step 2!
Step 2: Getting Type3= from pokemon.txt. This can seem quite complex. Don't worry! Take it slow, and make changes one step at a time. Personally I like to copy anything I'm changing, and then comment out the original with hashtags (#) so that I have a backuhp in case something goes wrong. If something does go wrong, just revert to the previous step!
Still in Compiler, find the following section:
This is what reads Type2 from pokemon.txt, and if it's missing makes it the same as Type1. Thankfully we don't have to modify this at all.
Instead, just before the first line, insert this line:
What this does is checks to see if Type3 is missing or blank and if it is, does something (in our case, we'll be making it set Type3 to Type2).
Now to actually assign Type3 we need to put something after:
We need to assign Type3. To do that, add this on the next line:
And we're done with step 2! At this point our code should look like this:
Step 3: Assigning the type to a Pokemon.
Go to PokeBattle_Pokemon (it should be near the very bottom of the list), and search for:
Beneath that section, add this:
It's that simple! Almost. We also have to do some work to PokeBattle_Battler. Head over there and find where it says "attr_accessor :type2". Just beneath that add in "attr_accessor :type3". Likewise beneath
add
(Note: This happens in two places, don't miss one!)
Under def pbInitBlank, find:
and add
Under def pbUpdate, find:
and add
def pbHasType? also needs modification. Search for it and replace it with:
Next do a search for "[PBEffects::Type3]". There will be many results. For each of them, you'll have to change it to type3. How varies from use to use, but just look for how type1 and type2 are handelled and mimic that. This is the long, boring part.
For Roost, we need to make sure that all instances of flying are removed. To do so find it in PokeBattle_Move and PokeBattle_AI replace it with the following (in both cases it's prefaced with "# Roost", so search for that) (thanks James Davy!):
Step 4: Showing the type on a summary screen. This part is as tricky as you want it to be. Three types don't fit nicely on the current summary screen so you have two options: Ignore it, or change the graphics yourself. If you do want to change the graphics yourself, the Summary background can be found at /Graphics/Pictures/summary1.png.
Now if you want to just ignore it, the three icons fit neatly enough that it shouldn't be an issue, it'll just look slightly weird. A word of warning, this only works with the default summary screen, as the information is layered on top of it. If you're using a custom summary screen you may have to fiddle with the values.
To start, find the following in PScreen_Summary:
Just beneath that line, add the following:
Then a bit bellow that you should find:
We're about to change this massively. Replace the entire section between the above and:
With the following (NOTE! Make sure NOT to remove "if pokemon.level<PBExperience::MAXLEVEL"):
Our code should now look like this:
Check it out! Add a third type to a Pokemon, go to it's summary screen, and behold!
On to step 5!
Step 5: Correcting the modifiers. Without this step, types won't actually have an effect on how much damage is dealt.
Go to PBTypes_Extra, and replace PBTypes.getCombinedEffectiveness with the following (Credit: James Davy):
Step 6: Enjoy! There you have it. Now all you need to do is add a third type to a Pokemon and it will show up in game perfectly functional. Give Charizard that Dragon type! Beedrill that Flying type! It's now possible!
Credit to sonicfan7895 and James Davy, who helped me work out large swaiths of this code.
WARNING: This tutorial will break anything that relies upon [PBEffects::Type3], which is used for moves that assign a third type. It's possible to make those moves function and have three-typed Pokemon, but that is beyond the scope of this tutorial.
Step 1: Assign a free byte to your third type. The numbers available for use should be listed in def pbCompilePokemonData under Complier. For this example we'll be using "X" (make sure to use an actual number for yours).
To do this, find where "Type2" is in pbCompilePokemonData (just scroll down a bit), and copy it. Then change the name from "Type2" to "Type3". Your code should look something like this:
Code:
"Habitat"=>[7,...],
"Type2"=>[9,"e",PBTypes],
"Type3"=>[X,"e",PBTypes],
"HiddenAbility"=>[40,...],
Great, now we've established a data byte for our third type, on to step 2!
Step 2: Getting Type3= from pokemon.txt. This can seem quite complex. Don't worry! Take it slow, and make changes one step at a time. Personally I like to copy anything I'm changing, and then comment out the original with hashtags (#) so that I have a backuhp in case something goes wrong. If something does go wrong, just revert to the previous step!
Still in Compiler, find the following section:
Code:
if !lastsection["Type2"] || lastsection["Type2"]==""
if !lastsection["Type1"] || lastsection["Type1"]==""
raise _INTL("No Pokémon type is defined in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
next
end
lastsection["Type2"]=lastsection["Type1"].clone[/]
end
This is what reads Type2 from pokemon.txt, and if it's missing makes it the same as Type1. Thankfully we don't have to modify this at all.
Instead, just before the first line, insert this line:
Code:
if !lastsection["Type3"] || lastsection["Type3"]==""
Now to actually assign Type3 we need to put something after:
Code:
lastsection["Type2"]=lastsection["Type1"].clone[/]
Code:
lastsection["Type3"]=lastsection["Type2"].clone
end
And we're done with step 2! At this point our code should look like this:
Code:
if !lastsection["Type3"] || lastsection["Type3"]==""
if !lastsection["Type2"] || lastsection["Type2"]==""
if !lastsection["Type1"] || lastsection["Type1"]==""
raise _INTL("No Pokémon type is defined in section {2} (PBS/pokemon.txt)",key,sectionDisplay) if hash==requiredtypes
next
end
lastsection["Type2"]=lastsection["Type1"].clone
end
lastsection["Type3"]=lastsection["Type2"].clone
end
Step 3: Assigning the type to a Pokemon.
Go to PokeBattle_Pokemon (it should be near the very bottom of the list), and search for:
Code:
def type2
Code:
# Returns this pokemon's third type.
def type3
dexdata=pbOpenDexData
pbDexDataOffset(dexdata,@species,10)
ret=dexdata.fgetb
dexdata.close
return ret
end
Code:
@type2 = pkmn.type2
Code:
@type3 = pkmn.type3
Under def pbInitBlank, find:
Code:
@type2 = 0
Code:
@type3 = 0
Under def pbUpdate, find:
Code:
@type2 = @pokemon.type2
Code:
@type3 = @pokemon.type3
def pbHasType? also needs modification. Search for it and replace it with:
Code:
def pbHasType?(type)
ret=false
if type.is_a?(Symbol) || type.is_a?(String)
ret=isConst?(self.type1,PBTypes,type.to_sym) ||
isConst?(self.type2,PBTypes,type.to_sym) ||
isConst?(self.type3,PBTypes,type.to_sym)
else
ret=(self.type1==type || self.type2==type || self.type3==type)
end
return ret
end
Next do a search for "[PBEffects::Type3]". There will be many results. For each of them, you'll have to change it to type3. How varies from use to use, but just look for how type1 and type2 are handelled and mimic that. This is the long, boring part.
For Roost, we need to make sure that all instances of flying are removed. To do so find it in PokeBattle_Move and PokeBattle_AI replace it with the following (in both cases it's prefaced with "# Roost", so search for that) (thanks James Davy!):
Code:
if isConst?(otype1,PBTypes,:FLYING) && opponent.effects[PBEffects::Roost]
# the following if statement checks if a Pokémon is a mono-Flying type
if isConst?(otype2,PBTypes,:FLYING) && (isConst?(otype3,PBTypes,:FLYING) ||
otype3==-1)
otype1=getConst(PBTypes,:NORMAL) || 0
else
otype1=otype2
end
end
if isConst?(otype2,PBTypes,:FLYING) && opponent.effects[PBEffects::Roost]
otype2=otype1
elsif isConst?(otype3,PBTypes,:FLYING) && opponent.effects[PBEffects::Roost]
otype3=-1
end
Step 4: Showing the type on a summary screen. This part is as tricky as you want it to be. Three types don't fit nicely on the current summary screen so you have two options: Ignore it, or change the graphics yourself. If you do want to change the graphics yourself, the Summary background can be found at /Graphics/Pictures/summary1.png.
Now if you want to just ignore it, the three icons fit neatly enough that it shouldn't be an issue, it'll just look slightly weird. A word of warning, this only works with the default summary screen, as the information is layered on top of it. If you're using a custom summary screen you may have to fiddle with the values.
To start, find the following in PScreen_Summary:
Code:
type2rect=Rect.new(0,pokemon.type2*28,64,28)
Code:
type3rect=Rect.new(0,pokemon.type2*28,64,28)
Then a bit bellow that you should find:
Code:
if pokemon.type1==pokemon.type2
Code:
if pokemon.level<PBExperience::MAXLEVEL
Code:
if pokemon.type1==pokemon.type2
overlay.blt(436,146,@typebitmap.bitmap,type1rect) # If just one, display in middle
elsif pokemon.type2==pokemon.type3
overlay.blt(370,146,@typebitmap.bitmap,type1rect) # If just two, display type 1 in middle
overlay.blt(436,146,@typebitmap.bitmap,type2rect) # And type 2 to the right
else
overlay.blt(304,146,@typebitmap.bitmap,type1rect) # Else type 1 on the left
overlay.blt(370,146,@typebitmap.bitmap,type2rect) # Type 2 in the middle
overlay.blt(436,146,@typebitmap.bitmap,type3rect) # And type 3 on the right
end
Our code should now look like this:
Code:
type2rect=Rect.new(0,pokemon.type2*28,64,28)
type3rect=Rect.new(0,pokemon.type3*28,64,28)
if pokemon.type1==pokemon.type2
overlay.blt(436,146,@typebitmap.bitmap,type1rect) # If just one, display in middle
elsif pokemon.type2==pokemon.type3
overlay.blt(370,146,@typebitmap.bitmap,type1rect) # If just two, display type 1 in middle
overlay.blt(436,146,@typebitmap.bitmap,type2rect) # And type 2 to the right
else
overlay.blt(304,146,@typebitmap.bitmap,type1rect) # Else type 1 on the left
overlay.blt(370,146,@typebitmap.bitmap,type2rect) # Type 2 in the middle
overlay.blt(436,146,@typebitmap.bitmap,type3rect) # And type 3 on the right
end
if pokemon.level<PBExperience::MAXLEVEL
Check it out! Add a third type to a Pokemon, go to it's summary screen, and behold!
On to step 5!
Step 5: Correcting the modifiers. Without this step, types won't actually have an effect on how much damage is dealt.
Go to PBTypes_Extra, and replace PBTypes.getCombinedEffectiveness with the following (Credit: James Davy):
Code:
def PBTypes.getCombinedEffectiveness(attackType,opponentType1,opponentType2=nil,opponentType3=nil)
if opponentType2==nil # checking if the first and second types matched was redundant as the mod2 assignment will show
return PBTypes.getEffectiveness(attackType,opponentType1)*2 # return the effectiveness value against the single type
else
mod1=PBTypes.getEffectiveness(attackType,opponentType1)
# the ternary operator here checks if the primary and secondary types match and sets a flat value of 2 if they do;
# otherwise it will set mod2 to the secondary type's effectiveness value
mod2=(opponentType1==opponentType2) ? 2 : PBTypes.getEffectiveness(attackType,opponentType2)
# the ternary operator here checks if the tertiary type doesn't exist and sets a flat value of 2 if the condition
# is true; otherwise it will set mod3 to the tertiary type's effectiveness value
mod3=(opponentType3==nil) ? 2 : PBTypes.getEffectiveness(attackType,opponentType3)
return (mod1*mod2*mod3) # returns the three effectiveness values multiplied together
end
end
Step 6: Enjoy! There you have it. Now all you need to do is add a third type to a Pokemon and it will show up in game perfectly functional. Give Charizard that Dragon type! Beedrill that Flying type! It's now possible!
Credit to sonicfan7895 and James Davy, who helped me work out large swaiths of this code.