Binary Hack Tutorials
Yellow Hacking Tutorial (Evolve/Replace Pikachu and more) + Pokemon Sprites
Started by longlostsoldier March 10th, 2017 9:09 PM- 7852 views
- 0 replies
Yellow Hacking Tutorial (Evolve/Replace Pikachu and more)
========================================================
Yellow is very similar to RGB, so you'll definitely want to review other guides. This will mooooostly focus on Yellow-specific things - evolving Pikachu,Making All Pokemon Follow or replacing with a different pokemon, but there will also be other things like biking, shinies and an uber uber basic item system.
First off - you will want to grab Yellow Disassembly and a program like Cygwin to make it compile.
You'll want Dannye-33's Gen 2 Sprites Base, because it's got more features than vanilla yellow, better graphics, and makes it a breeze to add in extra new gen pokemon. If you are nostalgic for any of the old yellow sprites, it's very easy to just copypaste from a vanilla yellow disassembly into the appropriate folder: I did that for Pikachu myself (revamping the image while I was at it) and left the others alone.
Altering Our Starter
===========================
Evolve Pikachu into Raichu
---
Alright! The bulk of this tutorial is devoted to Pikachu (specifically, replacing it). As appropriate of a Yellow tutorial. Even if you aren't interested in Raichu specifically and just came here to turn Pikachu into Meowth or something, you'll still learn a lot here that will enable us to do things like that, or evolve said Meowth, so let's start:
The method I prefer is 'evolve by happiness'. This ensures that you get to have Raichu emotion sprites at the appropriate times without too much fuss, although there will still probably be times when the player gets the wrong emotion sprite, the vast majority of the time they will get the right one.
Figure out what happiness level you want Pikachu to evolve at, and alter all the images of that happiness up accordingly in gfx/pikachu. For your convenience I have included a folder where this has already been done for you!
Next: Go to Pikachu's evo_moves.asm data, and change her evolution method to 'Level Up'. You probably want to choose a nice minimum level like 16 to discourage potion or turbo-run hax for early game Raichu. If you really want, though, you can set it to 1.
Then, go into the engine/evos_moves.asm and alter the level up function to check if the pokemon is pikachu, and for that happiness, and if so to skip straight to evolving.
code example: (search for .checkLevel and .doEvolution, and fix to look like this)
---
This is the most interesting and painstaking part. You will need to go to each place that loads pikachu's sprite - there's one buffer that is used to reload the sprite after emotions, and two loading functions depending on if you are indoors or outdoors. Add a check if Raichu or Pikachu is in the party, then load the correct sprite depending.
go to engine/overworld/map_sprites.asm
First, InitOutsideMapSprites:
change .loadSpriteSet to something like this:
Then, in the same file, find
LoadSpriteSetFromMapHeader:
;and alter the first bit of code there
in engine/pikachu_movement, need to alter LoadPikachuSpriteIntoVRAM to something like this:
Second, you will need to go in for any place that checks for Pikachu in your party, and add a second check for Raichu, so that Raichu's happiness can grow, you can have appropriate Raichu emotion sprites, and you can get Bulbasaur if you have a Raichu.
engine/pikachu_status is the place to alter here (this is a bit long, and there may be a more efficient way of coding this, buuut I'm still a novice so it's what you get):
And, less important but still good to do, is altering in the same file IsThisPartymonStarterPikachu_Party, and the IsThisSurfpikachu check , where it CPs for Pikachu, do something like this:
If the original does cp +1, +1 as well.
Now your Raichu can let you play the surfing minigame! Nice, huh? It'll still have a Pikachu sprite, but you could always replace that with a Raichu if you want.
You also need to create a sprite for Raichu if you haven't yet.
data/sprite_sets.asm, and in engine/bank3f just duplicate the PikachuSprite(s) there and include your image! This is quite important, as obviously you won't get a following Raichu otherwise!
Altering Pikachu's Voice / Changing voice on evolve
---
It is very simple, it involves replacing pikachu voice .wav files with other .wav files, or finding where they are called and choosing to play a different cry.
If some voices are only played at a certain happiness level, then one can just replace those with Raichu/evolved form without having to do any extra special checks.
You will also want to go to engine/battle/core.asm and to status_screen.asm to go put in a quick check for Raichu/Pikachu and load the right cry.
Like so:
Different Starter (Replace Pikachu and Raichu)
----
Having just Pikachu as your only option is boring, right? Let's change that up.
First, start with the 'Evolve Pikachu' and 'Make Raichu Follow' code above so your new starter can evolve and still follow you around. (skip if you don't want any evolutions) Hypothetically you can do this with multiple evolutions, not just two, just choose another happiness level to evolve at for that 3rd evolution to make your final starter follower and duplicate Raichu check codes again.
There are two different routes you can take: you can replace Pikachu and Raichu with fakemon, or you can simply leave Pikachu and Raichu in the game and switch all the places that check for Pikachu (same ones as in the Raichu code above!) with a different pokemon, so:
cp PIKACHU
becomes
cp MEOWTH
or something like that.
It's not strictly necessary to rename PikachuSprite - no one in game will see the code, so it's just sufficient to change the image to your new pokemon. Duplicate for Raichu with any evolutions.
If you are replacing your entire Pokedex with Fakemon (or next gen pokemon), chances are you will still have to do the above, since I imagine you'll be wanting to rename your constants.
Here's a quick list of places you need to alter (or add stuff on to) for new pokemon:
/pics folder, both the backsprites (/monback) and frontsprites (/ymon)
main.asm (need to include said pics so the game knows where to find them)
pokemon and pokedex constants
everywhere in /data that talks about pokemunz, such as evos_moves and base_stats.
/data/wildPokemon the wild pokemon,
/data/baseStats individual pokemon.asms such as pikachu.asm. (Update base_stats to include any new asm.)
data/ cries, mon_party_sprites, mon_palettes
alter monster names and pokedex entries in /text
You might want to consider altering pikachu's voice too. (Edit: On analysis I found you can just easily edit out calls to pikachu's voice in pikachu_emotions)
Of course, last part needed for a new following starter is to, once again, change the pikachu emotion sprites! If you enjoy image crafting, this is the most fun and easy part, just open up in an image editor (edit: that accepts indexing) and save!
If you hate image drawing, on the other hand, perhaps consider some generic emotion sprites instead, like a ! mark. Your image should only use 4 colors - the image itself can be black, gray and white, since the game will load colors based on palette.
All Pokemon Follow (Now a simple version is complete!)
-----
The coding has been done for making any pokemon follow. It basically replaces the CheckForRaichu and makes a new happiness checker for any pokemon that isn't Pikachu. I split the old CheckforRaichu into two different functions; one to dynamically load the right sprite, and one to check if you have a pokemun in your party's first row.
You may want to replace the pikachu happiness images with generic emotion symbols / smiley faces like SoulSilver and HeartGold does and create some other method for dealing with happiness or allow pokemon happynuzz to all be tied together.
However, I present an alternative system of keeping Pikachu happiness as-is and having other pokemon have happiness based on HP stat exp. You can just comment out the pikachu picture anims and use the game's exclamation, hate and heart symbols.
Check Any Pokemon
I put both of these code in pikachu_status, and called them from the map sprite loader functions I talked about earlier. In this code, I chose to check against either species or type, and basically went with what I had sprites for. If your sprite doesn't have full walk animations, it WILL glitch and look terrible, so make sure it matches pikachu's sprite image set size.
Note that unlike the original full code that checks for OT id and such, this one doesn't care if the pokemon is traded.
If you want to use Pikachu's happiness/status function, you still have to modify IsPikachuParty, instead of IsPikachuInOurParty, to accept all mons, as that's the function that checks status I think. Without it, only Pikachu/Raichu will get happiness updates when you do things with them. Personally I prefer the idea of developing a separate happiness function for the rest of them (see further below).
note: By default, the bird sprite, surf/seel sprite, and the slowbro sprite should have full walking sprites.
Here's the Loading Sprites function, you'll want to modify it to match your own game; for instance, mine has an eevee sprite so I added code for eevee. It got bloated pretty quickly :P.
Just like we did in the Raichu tutorial above, you'll want to put calls to this in engine/overworld/map_sprites.asm so both of the map sprite loading functions there will know what sprite to use.
VRAM:
Here's a quick example of modifying what emotion sprites come up for non-pikachu mons:
in pikachu_emotions, you'll find .check_pikachu_status, alter the start of it:
;pikaemotion_pikapic PikaPicAnimScript24
then that'll do it. Only the exclamation point will play, and you won't get Pikachu sprites for the other pokemon anymore.
You could also try making your own emotion scripts. I'll show that shortly.
Remember to put in some function for just pikachu/raichu detection, if you want to treat them specially:
Here's a function for alternative happiness:
Then do a more elaborate modification of happiness in pikachu_emotions:
Here's some generic replacement emotions you might like, remember to modify both pikachu_emotions (data and engine), one to add these and another has a little table listing all the emotes:
===
Running can be done the exact same way as in Red, but it will cause Pikachu to lag behind. Provided you don't mind this, it works just fine. Pikachu will eventually catch up. Credit goes to Red++ Matteo.
I just stuck this in overworld.asm in dobikespeedup, and it worked fine. You'll want to speed up the normal bike, which brings me to....
Altered Biking in Yellow
===
This can be a pain if you are adding a girl or extra selectable character (there's a tutorial floating around somewhere on it - it just requires going in to all the places that call a boy image and adding a girl flag check, plus option to choose gender in the intro -), because you'll likely immediately run into BANK0 TOO FULL error when you try to add the extra bike image checks.
As such, I opted for Pokemon Riding instead, since it just requires changing the bike image to a pokemon. (I also sped up my bike - now a pokemon - with an extra call AdvancePlayerSprite in the BikeSpeedUp function in overworld.asm)
You don't have to do the same, but it may be less hassle for you.
New, Multiple SHINIES
===
(This is just a quick tut on how to do multiple shinies, not shinies in general; the full code there is in Red++)
I altered status_screen, super_palettes (just to add one more palette is all, add as many shiny palettes as you want)
engine/palettes.asm:
NEW, ADDING HOLD ITEMS!
==============================
Edit Note: There's a part of it that is bizarrely finicky. One version of my game only accepts value 20 (or super potion) another, more recent one wanted value 21 set to the item id var on party screen load and map screen load. So be careful with this or it will crash your game, and double check it on any changes you make to the game that it's still working. I suspect this is an indicator I'm doing something wrong.
Alter items.asm, start_sub_menus, battle/core.asm, engine/menu/status_screen.asm and text_ids2. ^_^ I also altered all of the pokemon's catch rates so they would either be above my item range or valid items within that range. If you want you can personally over-ride so all caught pokemon will have catch rate of the same item, in Yellow just search for where it alters Kadabra's catch rate.
This is a _very_ basic item system, I encourage you to develop it further than this.
first ,items.asm:
text_ids2.asm:
alter this:
[/code]
.StatusWritten
coord hl, 9, 6
;ld de, StatusText;old status text, which just says 'status'
;call PlaceString ; "STATUS/"
ld a, [wLoadedMonCatchRate]
cp 100
jr c, .cnt ;replace 100 above with whatever your max item is, a guard against invalid values
ld a, 20
ld [wLoadedMonCatchRate],a
.cnt
ld [wd11e],a ; store item ID for GetItemName
call GetItemName
ld de,wcd6d;PokeHoldItemText;
call PlaceString
[/code]
In core.asm, to have it actually happen in battle, also alter
I commented out a lot of mine because right now I just want enemies to heal up, my bank was running out of space, and didn't feel like moving around stuff just yet to free up space.
The biggest problem with this code is making an enemy pokemon potentially easier to catch when you alter their item, since catchrate is same as item. Also, items are infinitely reusable after the battle ends, since there is no code for 'no item held' yet nor any permanent replacement mechanism here. However, if you're developing perma-held items like Mega Evolution Stones, that works great.
-----
Common Bugs -
BANK TOO FULL.
Yellow has less room in a lot of its banks, so you'll run into this very quickly. Some stuff can be shifted to a different bank with no problem, some code is superfluous and can be edited out (For instance, functions with a comment next to them saying 'Unused'.) but sometimes you have to be more careful. Things in banks often call in other things in that bank - I've switched from call to callab with no problems in these instances in the case of functions.
You also need to be careful with images; if something calls a set of images from one bank, and you moved one of those, you'll need to update that code to tell it the new bank to use. In the case of adding new pokemon, I highly recommend Dannye-33's Yellow Gen 2 Sprites Base instead of vanilla pokemon yellow disassembly. All you have to do there for new pokemon images having different banks is to go into their main datafile (such as pikachu.asm) and add the bank on the end! Viola! No more bank troubles.
My Added New Species Turned Into a Trainer!
If you add over 201 species, those over that number will turn into trainers in the wild. Annoying, I know. I believe there is a 'expand past 255 pokemon' project that fixes this and does all the hard work of adding pokemon for ya -wink-, it's for pokered but Yellow is similar so a lot of code, maybe even all, should be portable over. I haven't done this myself though.
My new pokemon turned into an ugly blob! / My pikachu emotion sprite is messed up!
You need to be careful that your image isn't too big or contains too many colors. I recommend a program like gale that can reduce colors to a small palette and then draw with them. What I like to do is duplicate an existing game-friendly image and then just blank it out and draw over that.
-------------
If you want to see some results of this code in action, check out my Yellow hack's screenshots in my hack's thread. Or play the game yourself - it's the first and currently the only hack with an evolving following pokemon, but hopefully with this tutorial that won't stay true for long!
UPDATE:
I've added some extra walking sprites that you can replace pikachu and raichu with. If you are lazy, you can just rename the sprite in question 'pikachu' and put it in the proper folder and it'll work like a charm. Partial credit goes to Dannye-33 for the Persian, Meowth, Eevee, Butterfree, Ghost, Ditto, Zubat, Dratini, Geodude, Fish.
Gyarados's partial credit goes to emimonserrate, who made the sprite I based the walkset on.
There is now a Github that contains the changes I speak of if you want to see it.
========================================================
Yellow is very similar to RGB, so you'll definitely want to review other guides. This will mooooostly focus on Yellow-specific things - evolving Pikachu,Making All Pokemon Follow or replacing with a different pokemon, but there will also be other things like biking, shinies and an uber uber basic item system.
First off - you will want to grab Yellow Disassembly and a program like Cygwin to make it compile.
You'll want Dannye-33's Gen 2 Sprites Base, because it's got more features than vanilla yellow, better graphics, and makes it a breeze to add in extra new gen pokemon. If you are nostalgic for any of the old yellow sprites, it's very easy to just copypaste from a vanilla yellow disassembly into the appropriate folder: I did that for Pikachu myself (revamping the image while I was at it) and left the others alone.
Altering Our Starter
===========================
Evolve Pikachu into Raichu
---
Alright! The bulk of this tutorial is devoted to Pikachu (specifically, replacing it). As appropriate of a Yellow tutorial. Even if you aren't interested in Raichu specifically and just came here to turn Pikachu into Meowth or something, you'll still learn a lot here that will enable us to do things like that, or evolve said Meowth, so let's start:
The method I prefer is 'evolve by happiness'. This ensures that you get to have Raichu emotion sprites at the appropriate times without too much fuss, although there will still probably be times when the player gets the wrong emotion sprite, the vast majority of the time they will get the right one.
Figure out what happiness level you want Pikachu to evolve at, and alter all the images of that happiness up accordingly in gfx/pikachu. For your convenience I have included a folder where this has already been done for you!
Next: Go to Pikachu's evo_moves.asm data, and change her evolution method to 'Level Up'. You probably want to choose a nice minimum level like 16 to discourage potion or turbo-run hax for early game Raichu. If you really want, though, you can set it to 1.
Then, go into the engine/evos_moves.asm and alter the level up function to check if the pokemon is pikachu, and for that happiness, and if so to skip straight to evolving.
code example: (search for .checkLevel and .doEvolution, and fix to look like this)
.checkLevel ld [hl], c ld a, [wEvoOldSpecies] cp PIKACHU jr nz, .CheckL ;160 is happiness level you have when you get to arms raised pikachu. I think? ld a, [wPikachuHappiness] cp 160 jp c, .nextEvoEntry2 jp c, .doEvolution .CheckL ld a, [hli] ; level requirement ld b, a ld a, [wLoadedMonLevel] cp b ; is the mon's level less than the evolution requirement? jp c, .nextEvoEntry2 ; if so, go the next evolution entry .doEvolutionMaking Raichu Follow
---
This is the most interesting and painstaking part. You will need to go to each place that loads pikachu's sprite - there's one buffer that is used to reload the sprite after emotions, and two loading functions depending on if you are indoors or outdoors. Add a check if Raichu or Pikachu is in the party, then load the correct sprite depending.
go to engine/overworld/map_sprites.asm
First, InitOutsideMapSprites:
change .loadSpriteSet to something like this:
Spoiler:
.loadSpriteSet ld a, b ld [wSpriteSetID], a dec a ld c, a ld b, 0 ld a, (wSpriteSetID - wSpriteSet) ld hl, SpriteSets call AddNTimes ; get sprite set offset ld de, wSpriteSet ld bc, (wSpriteSetID - wSpriteSet) call CopyData ; copy it to wSpriteSet ;change wSpriteSet here to Raichu if you want a Raichu. but what to check, hmm... how about a new function cloned from IsStarterPikachuInOurParty to check for Raichu instead? Worked for me. callab IsStarterRaichuInOurParty jr nc, .nope ld a, SPRITE_RAICHU ld [wSpriteSet], a .nope call LoadMapSpriteTilePatterns .skipLoadingSpriteSet call Func_14150 scf ret
Then, in the same file, find
LoadSpriteSetFromMapHeader:
;and alter the first bit of code there
Spoiler:
ld hl, wSpriteSet ld bc, (wSpriteSetID - wSpriteSet) xor a call FillMemory ld a, SPRITE_RAICHU ld [wSpriteSet], a ;load raichu on cert flag callab IsStarterPikachuInOurParty2 jr z, .nope ld a, SPRITE_PIKACHU ; load Pikachu separately ld [wSpriteSet], a .nope
in engine/pikachu_movement, need to alter LoadPikachuSpriteIntoVRAM to something like this:
Spoiler:
LoadPikachuSpriteIntoVRAM: callab IsStarterPikachuInOurParty2 jr nz, .Raichu ld de, PikachuSprite lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 jr .go .Raichu ld de, RaichuSprite lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 .go ld hl, vNPCSprites + $c * $10 push bc call CopyVideoDataAlternate callab IsStarterRaichuInOurParty jr z, .Pikachu2 ld de, RaichuSprite + $c * $10 jr .goo .Pikachu2 ld de, PikachuSprite + $c * $10 .goo ld hl, vNPCSprites2 + $c * $10 ld a, [h_0xFFFC] and a jr z, .load callab IsStarterRaichuInOurParty jr z, .Pikachu3 ld de, RaichuSprite + $c * $10 jr .goo2 .Pikachu3 ld de, PikachuSprite + $c * $10 .goo2 ld hl, vNPCSprites2 + $4c * $10 .load pop bc call CopyVideoDataAlternate call LoadPikachuShadowIntoVRAM call LoadPikachuBallIconIntoVRAM ret
Second, you will need to go in for any place that checks for Pikachu in your party, and add a second check for Raichu, so that Raichu's happiness can grow, you can have appropriate Raichu emotion sprites, and you can get Bulbasaur if you have a Raichu.
engine/pikachu_status is the place to alter here (this is a bit long, and there may be a more efficient way of coding this, buuut I'm still a novice so it's what you get):
Spoiler:
IsStarterPikachuInOurParty:: call IsStarterPikachuInOurParty2 jr nc, .checkR ret .checkR call IsStarterRaichuInOurParty ret IsStarterPikachuInOurParty2:: ld hl, wPartySpecies ld de, wPartyMon1OTID ld bc, wPartyMonOT push hl .loop pop hl ld a, [hli] push hl inc a jr z, .noPlayerPikachu cp PIKACHU + 1 jr nz, .curMonNotPlayerPikachu ld h, d ld l, e ld a, [wPlayerID] cp [hl] jr nz, .curMonNotPlayerPikachu inc hl ld a, [wPlayerID+1] cp [hl] jr nz, .curMonNotPlayerPikachu push de push bc ld hl, wPlayerName ld d, $6 ; possible player length - 1 .nameCompareLoop dec d jr z, .sameOT ld a, [bc] inc bc cp [hl] inc hl jr z, .nameCompareLoop pop bc pop de .curMonNotPlayerPikachu ld hl, wPartyMon2 - wPartyMon1 add hl, de ld d, h ld e, l ld hl, NAME_LENGTH add hl, bc ld b, h ld c, l jr .loop .sameOT pop bc pop de ld h, d ld l, e ld bc, -NAME_LENGTH add hl, bc ld a, [hli] or [hl] jr z, .noPlayerPikachu pop hl scf ret .noPlayerPikachu pop hl and a ret IsStarterRaichuInOurParty:: ld hl, wPartySpecies ld de, wPartyMon1OTID ld bc, wPartyMonOT push hl .loop pop hl ld a, [hli] push hl inc a jr z, .noPlayerPikachu cp RAICHU + 1 jr nz, .curMonNotPlayerPikachu ld h, d ld l, e ld a, [wPlayerID] cp [hl] jr nz, .curMonNotPlayerPikachu inc hl ld a, [wPlayerID+1] cp [hl] jr nz, .curMonNotPlayerPikachu push de push bc ld hl, wPlayerName ld d, $6 ; possible player length - 1 .nameCompareLoop dec d jr z, .sameOT ld a, [bc] inc bc cp [hl] inc hl jr z, .nameCompareLoop pop bc pop de .curMonNotPlayerPikachu ld hl, wPartyMon2 - wPartyMon1 add hl, de ld d, h ld e, l ld hl, NAME_LENGTH add hl, bc ld b, h ld c, l jr .loop .sameOT pop bc pop de ld h, d ld l, e ld bc, -NAME_LENGTH add hl, bc ld a, [hli] or [hl] jr z, .noPlayerPikachu pop hl scf ret .noPlayerPikachu pop hl and a ret
And, less important but still good to do, is altering in the same file IsThisPartymonStarterPikachu_Party, and the IsThisSurfpikachu check , where it CPs for Pikachu, do something like this:
cp RAICHU jr nz, .isPika jr .yes .isPika cp PIKACHU jr nz, .notPlayerPikachu .yesedit: I forgot in pikachu_emotions there is a check for sleeping, too.
If the original does cp +1, +1 as well.
Now your Raichu can let you play the surfing minigame! Nice, huh? It'll still have a Pikachu sprite, but you could always replace that with a Raichu if you want.
You also need to create a sprite for Raichu if you haven't yet.
data/sprite_sets.asm, and in engine/bank3f just duplicate the PikachuSprite(s) there and include your image! This is quite important, as obviously you won't get a following Raichu otherwise!
Altering Pikachu's Voice / Changing voice on evolve
---
It is very simple, it involves replacing pikachu voice .wav files with other .wav files, or finding where they are called and choosing to play a different cry.
If some voices are only played at a certain happiness level, then one can just replace those with Raichu/evolved form without having to do any extra special checks.
You will also want to go to engine/battle/core.asm and to status_screen.asm to go put in a quick check for Raichu/Pikachu and load the right cry.
Like so:
.playPikachuSoundClip callab IsStarterRaichuInOurParty ;really should make one to check box too... jr nc, .Pikachu ld e,4 ;load voice '5', which I changed to Raichu. Note e starts on 0 to load PikachuCry1. jr .cry .Pikachu ld e, 16 ;pikachu's original cry for this one. .cry callab PlayPikachuSoundClip jr .continueFor your convenience I have included several Raichu voices that I went to the trouble of cropping from the anime and putting into wav format.
Different Starter (Replace Pikachu and Raichu)
----
Having just Pikachu as your only option is boring, right? Let's change that up.
First, start with the 'Evolve Pikachu' and 'Make Raichu Follow' code above so your new starter can evolve and still follow you around. (skip if you don't want any evolutions) Hypothetically you can do this with multiple evolutions, not just two, just choose another happiness level to evolve at for that 3rd evolution to make your final starter follower and duplicate Raichu check codes again.
There are two different routes you can take: you can replace Pikachu and Raichu with fakemon, or you can simply leave Pikachu and Raichu in the game and switch all the places that check for Pikachu (same ones as in the Raichu code above!) with a different pokemon, so:
cp PIKACHU
becomes
cp MEOWTH
or something like that.
It's not strictly necessary to rename PikachuSprite - no one in game will see the code, so it's just sufficient to change the image to your new pokemon. Duplicate for Raichu with any evolutions.
If you are replacing your entire Pokedex with Fakemon (or next gen pokemon), chances are you will still have to do the above, since I imagine you'll be wanting to rename your constants.
Here's a quick list of places you need to alter (or add stuff on to) for new pokemon:
/pics folder, both the backsprites (/monback) and frontsprites (/ymon)
main.asm (need to include said pics so the game knows where to find them)
pokemon and pokedex constants
everywhere in /data that talks about pokemunz, such as evos_moves and base_stats.
/data/wildPokemon the wild pokemon,
/data/baseStats individual pokemon.asms such as pikachu.asm. (Update base_stats to include any new asm.)
data/ cries, mon_party_sprites, mon_palettes
alter monster names and pokedex entries in /text
You might want to consider altering pikachu's voice too. (Edit: On analysis I found you can just easily edit out calls to pikachu's voice in pikachu_emotions)
Of course, last part needed for a new following starter is to, once again, change the pikachu emotion sprites! If you enjoy image crafting, this is the most fun and easy part, just open up in an image editor (edit: that accepts indexing) and save!
If you hate image drawing, on the other hand, perhaps consider some generic emotion sprites instead, like a ! mark. Your image should only use 4 colors - the image itself can be black, gray and white, since the game will load colors based on palette.
All Pokemon Follow (Now a simple version is complete!)
-----
The coding has been done for making any pokemon follow. It basically replaces the CheckForRaichu and makes a new happiness checker for any pokemon that isn't Pikachu. I split the old CheckforRaichu into two different functions; one to dynamically load the right sprite, and one to check if you have a pokemun in your party's first row.
You may want to replace the pikachu happiness images with generic emotion symbols / smiley faces like SoulSilver and HeartGold does and create some other method for dealing with happiness or allow pokemon happynuzz to all be tied together.
However, I present an alternative system of keeping Pikachu happiness as-is and having other pokemon have happiness based on HP stat exp. You can just comment out the pikachu picture anims and use the game's exclamation, hate and heart symbols.
Check Any Pokemon
IsaPokemonInOurParty:: ld hl, wPartySpecies push hl .loop pop hl ld a, [hli] push hl inc a jr z, .noPlayerPoke ; cp WHATEVERPOKE + 1, if want all, just leave like this~ ; jr nz, .curMonNotPlayerPikachu call FirstPartymonHP cp 0 jr z, .noPlayerPoke pop hl scf ret .noPlayerPoke pop hl and a retFirst partymonHP (needed for fainting in the above function)
FirstPartymonHP:: ld hl, wPartyMon1 ld bc,(wPartyMon1HP + 1) - wPartyMon1 ;check hp add hl,bc ld a,[hl] ret
I put both of these code in pikachu_status, and called them from the map sprite loader functions I talked about earlier. In this code, I chose to check against either species or type, and basically went with what I had sprites for. If your sprite doesn't have full walk animations, it WILL glitch and look terrible, so make sure it matches pikachu's sprite image set size.
Note that unlike the original full code that checks for OT id and such, this one doesn't care if the pokemon is traded.
If you want to use Pikachu's happiness/status function, you still have to modify IsPikachuParty, instead of IsPikachuInOurParty, to accept all mons, as that's the function that checks status I think. Without it, only Pikachu/Raichu will get happiness updates when you do things with them. Personally I prefer the idea of developing a separate happiness function for the rest of them (see further below).
note: By default, the bird sprite, surf/seel sprite, and the slowbro sprite should have full walking sprites.
Here's the Loading Sprites function, you'll want to modify it to match your own game; for instance, mine has an eevee sprite so I added code for eevee. It got bloated pretty quickly :P.
Just like we did in the Raichu tutorial above, you'll want to put calls to this in engine/overworld/map_sprites.asm so both of the map sprite loading functions there will know what sprite to use.
LoadPokeFollowSprite:: ld hl, wPartySpecies push hl pop hl ld a, [hli] push hl inc a jp z, .noPlayerPoke CP PIKACHU +1 jr nz, .curMonNotThis0 ld a, SPRITE_PIKACHU .end pop hl scf ld [wSpriteSet], a ret .noPlayerPoke pop hl and a ret .curMonNotThis0 CP RAICHU +1 jr nz, .curMonNotThis1 ld a, SPRITE_RAICHU jr .end .curMonNotThis1 cp PERSIAN + 1 jr nz, .curMonNotThis2 ld a, SPRITE_PERSIAN jr .end .curMonNotThis2 cp BULBASAUR + 1 jr nz, .curMonNotThis3b ld a, SPRITE_BULBASAUR jr .end .curMonNotThis3b cp IVYSAUR + 1 jr nz, .curMonNotThis3c ld a, SPRITE_BULBASAUR jr .end .curMonNotThis3c cp VENUSAUR + 1 jr nz, .curMonNotThis3 ld a, SPRITE_BULBASAUR jr .end .curMonNotThis3 cp EEVEE + 1 jr nz, .curMonNotThis4a ld a, SPRITE_EEVEE jr .end .curMonNotThis4a cp SYLVEON + 1 jr nz, .curMonNotThis4b ld a, SPRITE_EEVEE jr .end .curMonNotThis4b cp UMBREON + 1 jr nz, .curMonNotThis4c ld a, SPRITE_EEVEE jr .end .curMonNotThis4c cp ESPEON + 1 jr nz, .curMonNotThis4d ld a, SPRITE_EEVEE jr .end .curMonNotThis4d cp FLAREON + 1 jr nz, .curMonNotThis4e ld a, SPRITE_EEVEE jr .end .curMonNotThis4e cp GLACEON + 1 jr nz, .curMonNotThis4f ld a, SPRITE_EEVEE jr .end .curMonNotThis4f cp JOLTEON + 1 jr nz, .curMonNotThis4g ld a, SPRITE_EEVEE jr .end .curMonNotThis4g cp VAPOREON + 1 jr nz, .curMonNotThisEon ld a, SPRITE_EEVEE jr .end .curMonNotThisEon cp LEAFEON + 1 jr nz, .curMonNotThis4 ld a, SPRITE_EEVEE jr .end .curMonNotThis4 cp DITTO + 1 jr nz, .curMonNotThisDitto ld a, SPRITE_DITTO jr .end2 .curMonNotThisDitto cp SQUIRTLE + 1 jr nz, .curMonNotThis5a ld a, SPRITE_SQUIRTLE jr .end2 .curMonNotThis5a cp WARTORTLE + 1 jr nz, .curMonNotThis5b ld a, SPRITE_SQUIRTLE jr .end2 .curMonNotThis5b cp LAPRAS + 1 jr nz, .curMonNotThisM ld a, SPRITE_LAPRAS jr .end2 .curMonNotThisM cp GYARADOS + 1 jr nz, .curMonNotThisFish ld a, SPRITE_GYARADOS jr .end2 .curMonNotThisFish cp SEEL + 1 jr nz, .curMonNotThisFishy ld a, SPRITE_SEEL jr .end2 .curMonNotThisFishy cp DEWGONG + 1 jr nz, .curMonNotThisFishfood ld a, SPRITE_SEEL jr .end2 .curMonNotThisFishfood cp SANDSHREW + 1 jr nz, .curMonNotThisShrew ld a, SPRITE_SANDSHREW jr .end2;relative value must be 8 bit .curMonNotThisShrew cp SANDSLASH + 1 jr nz, .curMonNotThisS ld a, SPRITE_SANDSHREW .end2;so, we have multiple different endings here pop hl scf ld [wSpriteSet], a ret .curMonNotThisS cp BLASTOISE + 1 jr nz, .curMonNotThis5 ld a, SPRITE_SQUIRTLE jr .end2 .curMonNotThis5 cp CHARIZARD + 1 jr nz, .curMonNotThis6a ld a, SPRITE_DRAGON jr .end2 .curMonNotThis6a cp CHARMELEON + 1 jr nz, .curMonNotThis6b ld a, SPRITE_CHARMANDER jr .end2 .curMonNotThis6b cp CHARMANDER + 1 jr nz, .curMonNotThisStarter ld a, SPRITE_CHARMANDER jr .end2 .curMonNotThisStarter cp DRAGONITE + 1 jr nz, .curMonNotThisG ld a, SPRITE_DRAGON jr .end2 .curMonNotThisG cp ONIX + 1 jr nz, .curMonNotThisMon ld a, SPRITE_SNAKE2 jr .end2 .curMonNotThisMon cp EKANS + 1 jr nz, .curMonNotThisMon2 ld a, SPRITE_SNAKE2 jr .end2 .curMonNotThisMon2 cp ARBOK + 1 jr nz, .curMonNotThisMon3 ld a, SPRITE_SNAKE2 jr .end2 .curMonNotThisMon3 cp VOLTORB + 1 jr nz, .curMonNotThisMon4 ld a, SPRITE_BALL jr .end2 .curMonNotThisMon4 cp ELECTRODE + 1 jr nz, .curMonNotThisMon5 ld a, SPRITE_BALL jr .end2 .curMonNotThisMon5 cp MAGNEMITE + 1 jr nz, .curMonNotThisMon6 ld a, SPRITE_BALL jr .end2 .curMonNotThisMon6 cp MAGNETON + 1 jr nz, .curMonNotThisMon7 ld a, SPRITE_BALL jr .resume .curMonNotThisMon7 cp MAGNEZONE + 1 jr nz, .curMonNotThisMon8 ld a, SPRITE_BALL jr .resume .curMonNotThisMon8 cp GLIGAR + 1 jr nz, .curMonNotThisMon9 ld a, SPRITE_ZUBAT jr .resume .curMonNotThisMon9 cp GLISCOR + 1 jr nz, .curMonNotThisMon10 ld a, SPRITE_ZUBAT jr .resume .curMonNotThisMon10 ld a,[wPartyMon1Type1] ; callab GetPartyMonSpriteID I didn't have much luck with this, also don't have enough sprites for all of them; they have to have full walksprites. ;cp SPRITE_MON ; $0 ;cp SPRITE_BALL_M ; $1 ;cp SPRITE_HELIX ; $2 cp FAIRY jr nz, .curMonNotThisFairy ld a, SPRITE_CLEFAIRY jr .resume .curMonNotThisFairy cp WATER jr nz, .curMonNotThisWater ld a, SPRITE_FISH jr .resume .curMonNotThisWater cp FIRE jr nz, .curMonNotThis6 ld a, SPRITE_DOG jr .resume .curMonNotThis6 cp BUG jr nz, .curMonNotThisBug ld a, SPRITE_BUTTERFREE jr .resume .curMonNotThisBug cp GRASS jr nz, .curMonNotThisGrass ld a, SPRITE_ODDISH jr .resume .curMonNotThisGrass cp DRAGON jr nz, .curMonNotThisDragony ld a, SPRITE_SNAKE2 jr .resume .curMonNotThisDragony cp ROCK jr nz, .curMonNotThis ld a, SPRITE_GEODUDE jr .resume .curMonNotThis cp GHOST jr nz, .curMonNotThisGhost ld a, SPRITE_GHOST jr .resume .curMonNotThisGhost cp POISON jr nz, .curMonNotThisPoison ld a, SPRITE_ZUBAT jr .resume .curMonNotThisPoison ld a,[wPartyMon1Type2] cp FLYING jr nz, .curMonNotThisBird ld a, SPRITE_BIRD jr .resume .curMonNotThisBird cp DARK jr nz, .curMonNotThisredux ld a, SPRITE_MEOWTH jr .resume .curMonNotThisredux ld a, SPRITE_SLOWBRO jr .resume .resume ld [wSpriteSet], a pop hl scf retso, using above, modify the various add/call sprite codes.
VRAM:
LoadPikachuSpriteIntoVRAM: call IsPikachuFirst cp 25 ;rather arbitrary value I asked pikachufirst to load... ld a,0 jr nz, .load2 call IsStarterPikachuInOurParty2 jr nc, .Raichu ld de, PikachuSprite ;lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 jr .go .Raichu ld de, RaichuSprite .go lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 ld hl, vNPCSprites + $c * $10 push bc call CopyVideoDataAlternate call IsStarterRaichuInOurParty jr nc, .Pikachu2 ld de, RaichuSprite + $c * $10 jr .goo .Pikachu2 ld de, PikachuSprite + $c * $10 .goo ld hl, vNPCSprites2 + $c * $10 ld a, [h_0xFFFC] and a jr z, .load callab IsStarterRaichuInOurParty jr nc, .Pikachu3 ld de, RaichuSprite + $c * $10 jr .goo2 .Pikachu3 ld de, PikachuSprite + $c * $10 .goo2 ld hl, vNPCSprites2 + $4c * $10 .load pop bc call CopyVideoDataAlternate .load2 call LoadPikachuShadowIntoVRAM call LoadPikachuBallIconIntoVRAM ret
Here's a quick example of modifying what emotion sprites come up for non-pikachu mons:
in pikachu_emotions, you'll find .check_pikachu_status, alter the start of it:
.check_pikachu_status call IsPikachuFirst cp 25 jr z, .Pika ldpikaemotion a, PikachuEmotion24;PikachuEmotion5 unhappy,28 status,29 heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim. jr c, .play_emotion .PikaI went in and disabled all the animation except the ! point for anim 24; it's for pikachu refusing to evolve and I don't really need it much. You can find PikachuEmotion24 in the other pikachu_emotions file, if you comment out:
;pikaemotion_pikapic PikaPicAnimScript24
then that'll do it. Only the exclamation point will play, and you won't get Pikachu sprites for the other pokemon anymore.
You could also try making your own emotion scripts. I'll show that shortly.
Remember to put in some function for just pikachu/raichu detection, if you want to treat them specially:
IsPikachuFirst:: ld hl, wPartySpecies push hl .loop pop hl ld a, [hli] push hl inc a jr z, .noPlayerPoke cp PIKACHU + 1 jr z, .curMonPlayerPikachu cp RAICHU + 1 jr nz, .noPlayerPoke .curMonPlayerPikachu ld a,25 ;completely arbitrary value to check for, as long as it ain't zero. >_> pop hl ret .noPlayerPoke ld a,0 pop hl retYou can alter sprite_sets and sprite_constants to add on new sprites like I did, or you can just replace old ones.
Here's a function for alternative happiness:
FirstPartymonHappy:: ld hl, wPartyMon1 ld bc,wPartyMon1HPExp - wPartyMon1 ;decided to base it off HP exp add hl,bc ld a,[hl] retit loads the "happiness" (really hp exp) into a.
Then do a more elaborate modification of happiness in pikachu_emotions:
.check_pikachu_status call IsPikachuFirst cp 25 jr z, .Pika call FirstPartymonHappy cp 1 jr nc, .content ;bigger than ldpikaemotion a, PikachuEmotionSkull jr .play_emotion .content cp 10 jr nc, .happy ldpikaemotion a, PikachuEmotion24;PikachuEmotion5 unhappy,28 status,29 exuberant heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim. jr .justlilhappy .happy cp 30 jr nc, .happy2 ldpikaemotion a, PikachuEmotionSmile;PikachuEmotion5 unhappy,28 status,29 exuberant heart 8 happy, 1 content, 32 confused, 27 shocked, 26 zz wakeup, 25 used attack, 24 exclaim. jr .justlilhappy .happy2 ldpikaemotion a, PikachuEmotionHeart .justlilhappy jr .play_emotion .Pikasmall edit: prev happiness standards were way too high. :P
Here's some generic replacement emotions you might like, remember to modify both pikachu_emotions (data and engine), one to add these and another has a little table listing all the emotes:
PikachuEmotionSmile: pikaemotion_dummy2 pikaemotion_emotebubble SMILE_BUBBLE db $ff PikachuEmotionHeart: pikaemotion_dummy2 pikaemotion_emotebubble HEART_BUBBLE db $ff PikachuEmotionSkull: pikaemotion_dummy2 pikaemotion_emotebubble SKULL_BUBBLE db $ffRunning in Yellow
===
Running can be done the exact same way as in Red, but it will cause Pikachu to lag behind. Provided you don't mind this, it works just fine. Pikachu will eventually catch up. Credit goes to Red++ Matteo.
ld a, [hJoyHeld] ; Check what buttons are being pressed for Shoes and B_BUTTON ; Are you holding B? jr z, .notRunning ; If you aren't holding B, skip ahead to step normally. jp .goFaster ; Needs to link or call to your method of going faster. Make you go faster if you were holding B .notRunning ; Normal code resumes here
I just stuck this in overworld.asm in dobikespeedup, and it worked fine. You'll want to speed up the normal bike, which brings me to....
Altered Biking in Yellow
===
This can be a pain if you are adding a girl or extra selectable character (there's a tutorial floating around somewhere on it - it just requires going in to all the places that call a boy image and adding a girl flag check, plus option to choose gender in the intro -), because you'll likely immediately run into BANK0 TOO FULL error when you try to add the extra bike image checks.
As such, I opted for Pokemon Riding instead, since it just requires changing the bike image to a pokemon. (I also sped up my bike - now a pokemon - with an extra call AdvancePlayerSprite in the BikeSpeedUp function in overworld.asm)
You don't have to do the same, but it may be less hassle for you.
New, Multiple SHINIES
===
(This is just a quick tut on how to do multiple shinies, not shinies in general; the full code there is in Red++)
I altered status_screen, super_palettes (just to add one more palette is all, add as many shiny palettes as you want)
engine/palettes.asm:
ld hl, MonsterPalettes ;shiny ld e, a ld d, $00 add hl, de ld a, [hl] push bc ld d, a ld a, e and a ld a, d jr z, .done ld b, a ld a, [wShinyMonFlag] bit 0, a ; is mon supposed to be shiny? ld a, b jr z, .done ld b, a ld a,[wTemp] ;Shinybit 1 cp 1 jr nz, .nextcolor ;ld a,b ;add (3) ; ld a, PAL_MEWTWO ;the best pokemon? >_> jr .done .nextcolor ld a,[wTemp] cp 2 jr nz, .nextcolor2 ld a,PAL_BLUEMON ; or maybe do PAL_NIDORINA ;add (3) jr .done .nextcolor2 ld a,[wTemp] cp 3 jr nz, .nextcolor3 ld a,PAL_YELLOWMON ;add (4) jr .done .nextcolor3 cp 5 jr nz, .nextcolor4 ld a,PAL_GREENMON ; jr .done .nextcolor4 cp 6 jr nz, .nextcolor5 ld a,PAL_SHINY ;blackmon jr .done .nextcolor5 ld a,[wTemp] cp 4 jr nz, .nope ld a,PAL_PINKMON ;ld a,b ;add (5) ;older version just shifted palettes forward. jr .done .nope ld a,b .done pop bc retand in main.asm, set the varieties/check for different shines!
IsMonShiny: ; Input: de = address in RAM for DVs ; Reset zero flag if mon is shiny ; Mon is shiny if Defense/Speed/Special are 10, and Attack is 2, 3, 6, 7, 10, 11, 14, or 15 ld h, d ld l, e ;Attack must be even2,odd1 (1, 3, 5, 7, 9, 11, 13, or 15) (1 in 2) ld a, [hl] and 2 << 4 jr z, .NotShiny ld a,0 ld [wTemp], a ld a, [hli] and $f cp 9 jr z, .MaybeShiny1 cp 8 jr z, .MaybeShiny2 cp 7 jr z, .MaybeShiny3 cp 2 jr z, .MaybeShiny4 cp 11 jr nz, .NotShiny .MaybeShiny1 ;color1 ld a, 1 ld [wTemp], a ld a, [hl] jr .Shiny .MaybeShiny2;color2 ld a, 2 ld [wTemp], a ld a, [hl] jr .Shiny .MaybeShiny4;color2 ld a, 4 ld [wTemp], a ld a, [hl] jr .Shiny .MaybeShiny3;color3 ld a, 3 ld [wTemp], a ld a, [hl] ;ol' speed check if we want to reduce values even more, would have to alter the maybe shinies above to go here instead of shiny. could also introduce even moar varieties of pokemonz. ;.shinyspeedcheck ;and $f << 4 ;cp 5 << 4 ;jr z, .Shiny ;cp 13 << 4 ;jr nz, .NotShiny .Shiny ; set zero flag and a ; a cannot be 0, so zero flag is set with thing command ret .NotShiny ; reset zero flag xor a retYou also of course have to do the calling for the shiny check in battle.
; is mon shiny? ld b, Bank(IsMonShiny) ld hl, IsMonShiny ld de, wEnemyMonDVs call Bankswitch ld hl, wShinyMonFlag jr nz, .shiny res 0, [hl] jr .setPAL .shiny set 0, [hl] .setPAL ld b, SET_PAL_BATTLE call RunPaletteCommand call HideSprites jpab PrintBeginningBattleText;search for this lineThis is just my example of modifying the shiny code, the original version you can check out in Red++; the only thing you have to worry about when porting it over to yellow is some variable names change slightly.
NEW, ADDING HOLD ITEMS!
==============================
Edit Note: There's a part of it that is bizarrely finicky. One version of my game only accepts value 20 (or super potion) another, more recent one wanted value 21 set to the item id var on party screen load and map screen load. So be careful with this or it will crash your game, and double check it on any changes you make to the game that it's still working. I suspect this is an indicator I'm doing something wrong.
Alter items.asm, start_sub_menus, battle/core.asm, engine/menu/status_screen.asm and text_ids2. ^_^ I also altered all of the pokemon's catch rates so they would either be above my item range or valid items within that range. If you want you can personally over-ride so all caught pokemon will have catch rate of the same item, in Yellow just search for where it alters Kadabra's catch rate.
This is a _very_ basic item system, I encourage you to develop it further than this.
first ,items.asm:
GivePokeHoldItem: ld a, 1 ld [wActionResultOrTookBattleTurn], a ; initialise to success value ld a,[wWhichPokemon] ld [wTempLevel],a ; remember which item slot was used ld a, [wcf91] ;contains item_ID? ld [wTemp],a cp 20 jr z, .works ld a, 20 ld [wcf91],a ;party menu isn't working right for anything EXCEPT super potion, equal to 20, bizarrely? probably because trying to load some value in same spot it originally saves item. so let's save the nonsuperpotion and then over-write... >_> meh. .works ld a, [wPartyCount] and a jp z, .canceledItemUse ld a, [wWhichPokemon] push af ld a, [wcf91] push af ld a, USE_ITEM_PARTY_MENU ld [wPartyMenuTypeOrMessageID], a ld a, $ff ld [wUpdateSpritesEnabled], a call DisplayPartyMenu .getPartyMonDataAddress jp c, .canceledItemUse ld hl, wPartyMons ld bc, wPartyMon2 - wPartyMon1 ld a, [wWhichPokemon] call AddNTimes ld a, [wWhichPokemon] ld [wUsedItemOnWhichPokemon], a ld d, a ld [wd0b5], a call GetMonHeader ld bc,wPartyMon1CatchRate - wPartyMon1 add hl,bc ; hl now points to catch, now item ld a, [hl] ;Let's do a check for what the item is cp 70 ; you need to put your max valid item count here jr c, .cnt ;less than than... ld a, 20 ;overwrite with potion if the catch rate of Mon is nonexistent item. ;ld [hl],a ;not necessary to actually do it yet since we overwrite shortly anyway .cnt ld [wTempCoins1], a ;hold bag id for laters ;Now give pokemon the new hold item. ;xor a ;remove catch, unnecessary but useful if we want no items by default. ld a, [wTemp];item ld [hl], a ;ld into CatchRate,a ld [wd11e],a ; store item ID for GetItemName call GetItemName call CopyStringToCF4B ; copy name to wcf4b ld hl, HoldItemText Call PrintText ;take away the old item held and give it to bag ld a, [wTempCoins1] ld [wcf91],a ;item id ld [wd11e],a ;fo item name ld hl, wNumBagItems ;put the address of bag in hl ld a,1 ld [wItemQuantity],a ;how many to add call AddItemToInventory call GetItemName call CopyStringToCF4B ; copy name to wcf4b ld hl, TookItemText Call PrintText ld a, 20 ld [wcf91],a ;overwrite fix fo map again... .nope ld a,[wTempLevel] ld [wWhichPokemon],a ld a, 1 ld [wItemQuantity],a ld hl, wNumBagItems call RemoveItemFromInventory ;needs wWhichPokemon to have itemslot in it. .canceledItemUse call GBPalWhiteOut call z, RunDefaultPaletteCommand ld a, [wIsInBattle] and a ret nz jp ReloadMapData HoldItemText:: text "Gave the item" line "@" TX_RAM wcf4b ;some variable goes here text "." prompt TookItemText:: text "Took away the item" line "@" TX_RAM wcf4b ;some variable goes here text "." prompt
text_ids2.asm:
alter this:
UseTossText: db "USE" next "GIVE" next "[email protected]"and in start_sub_menus:
.notBicycle2 ld a,[wCurrentMenuItem] ;and a cp a, 2 jr z, .tossItem cp a, 1 jr z, .giveItem1 ; use item jr .useitem .giveItem1 ld b,a ld a,8 ld [wTemp],a ld a,b .useitem ld [wPseudoItemID],a ; a must be 0 due to above conditional jump ld a,[wcf91] cp a,HM_01 jr nc,.useItem_partyMenu ld hl,UsableItems_CloseMenu ld de,1 call IsInArray jr c,.useItem_closeMenu ld a,[wcf91] ld hl,UsableItems_PartyMenu ld de,1 call IsInArray jr c,.useItem_partyMenu call UseItem jp ItemMenuLoop .useItem_closeMenu ;ld a,[wTemp] ;cp a, 8 ;jr z, .giveItem ;don't want this one xor a ld [wPseudoItemID],a call UseItem ld a,[wActionResultOrTookBattleTurn] and a jp z,ItemMenuLoop jp CloseStartMenu .useItem_partyMenu ld a,[wTemp] cp a, 8 jr z, .giveItem ;hopefully works ld a,[wUpdateSpritesEnabled] push af call UseItem ld a,[wActionResultOrTookBattleTurn] cp a,$02 jp z,.partyMenuNotDisplayed call GBPalWhiteOutWithDelay3 call RestoreScreenTilesAndReloadTilePatterns pop af ld [wUpdateSpritesEnabled],a jp StartMenu_Item .partyMenuNotDisplayed pop af ld [wUpdateSpritesEnabled],a jp ItemMenuLoop .tossItem call IsKeyItem ld a,[wIsKeyItem] and a jr nz,.skipAskingQuantity ld a,[wcf91] call IsItemHM jr c,.skipAskingQuantity call DisplayChooseQuantityMenu inc a jr z,.tossZeroItems .skipAskingQuantity ld hl,wNumBagItems call TossItem .tossZeroItems jp ItemMenuLoop .giveItem ld a,[wUpdateSpritesEnabled] push af callab GivePokeHoldItem ld a,[wActionResultOrTookBattleTurn] cp a,$02 jp z,.partyMenuNotDisplayed call GBPalWhiteOutWithDelay3 call RestoreScreenTilesAndReloadTilePatterns pop af ld [wUpdateSpritesEnabled],a jp StartMenu_Itemstatus_screen.asm:
[/code]
.StatusWritten
coord hl, 9, 6
;ld de, StatusText;old status text, which just says 'status'
;call PlaceString ; "STATUS/"
ld a, [wLoadedMonCatchRate]
cp 100
jr c, .cnt ;replace 100 above with whatever your max item is, a guard against invalid values
ld a, 20
ld [wLoadedMonCatchRate],a
.cnt
ld [wd11e],a ; store item ID for GetItemName
call GetItemName
ld de,wcd6d;PokeHoldItemText;
call PlaceString
[/code]
In core.asm, to have it actually happen in battle, also alter
ApplyAttackToEnemyPokemonDone: ;######HOLD ITEM SCRIPT! @@@####; ld a, [wBattleMonCatchRate] cp FULL_HEAL ;is it potionz? jr c, .IsItOther ld a,0 ld [wBattleMonStatus],a jr .NoUseBerry .IsItOther cp POTION ;is it potionz jr c, .IsItOther2 ld b,10 jr .UseHealBerry .IsItOther2 cp SUPER_POTION ;is it potionz? jr c, .NoUseBerry ld b,20 .UseHealBerry ld a, [wBattleMonHP + 1] cp 15;less than 15 health, use a held item. jr nc, .NoUseBerry ;if bigger than above, don't use ld a,[wBattleMonHP + 1] ;ld b, 10 add b ld b,a ld a,[wBattleMonMaxHP +1] cp b jr nc, .ContUseItem ;if maxhp bigger than b, continue ld a,[wBattleMonMaxHP +1] ; full restore ld b,a .ContUseItem ld a, b ld [wBattleMonHP + 1],a ld [wHPBarNewHP],a ld a,FULL_RESTORE ld [wBattleMonCatchRate], a ;replace with diff item after use...doesn't seem to work permanently callab PrintHoldItemText .NoUseBerry jp DrawHUDsAndHPBarsDo same thing to Apply Damage to Player Done for items, but with different vars.
I commented out a lot of mine because right now I just want enemies to heal up, my bank was running out of space, and didn't feel like moving around stuff just yet to free up space.
The biggest problem with this code is making an enemy pokemon potentially easier to catch when you alter their item, since catchrate is same as item. Also, items are infinitely reusable after the battle ends, since there is no code for 'no item held' yet nor any permanent replacement mechanism here. However, if you're developing perma-held items like Mega Evolution Stones, that works great.
ApplyAttackToPlayerPokemonDone: ;######HOLD ITEM SCRIPT! @@@####; ld a, [wEnemyMonCatchRate] cp 99 ;Enemies with catch rate lower than that should use items. jr nc, .NoUseBerry ld a, [wEnemyMonHP + 1] cp 10;less than 10 health, use a held item. jr nc, .NoUseBerry ;if bigger than, don't use ;ld b,10 ;better heal. you can uncomment this stuff if you want ;ld a,[wEnemyMonHP + 1] ;add b ;ld b,a ;ld a,[wEnemyMonMaxHP +1] ;cp b ;jr nc, .ContUseItem ;if maxhp bigger than b, continue ;ld a,[wEnemyMonMaxHP +1] ; full restore instead of letting HP overflow ;ld b,a ;.ContUseItem ld a, 15 ;originally load b, to be more dynamic, but no point to that here. not enough bank space atm, would have to move stuff around ld [wEnemyMonHP + 1],a ld a,100 ld [wEnemyMonCatchRate], a ;replace with diff item after use...doesn't seem to work permanently. anyway, may make a poke easier to catch. >_> callab PrintHoldItemText .NoUseBerry jp DrawHUDsAndHPBarsPut this wherever you want, if in same bank then just use call instead of callab:
UseHoldItemText:: text "The PKMN ate a little!" ;line "@" ;TX_RAM wcf4b ;some variable goes here if we want, could put in the item name. ;text "." prompt PrintHoldItemText: ld hl,UseHoldItemText Call PrintText ret
-----
Common Bugs -
BANK TOO FULL.
Yellow has less room in a lot of its banks, so you'll run into this very quickly. Some stuff can be shifted to a different bank with no problem, some code is superfluous and can be edited out (For instance, functions with a comment next to them saying 'Unused'.) but sometimes you have to be more careful. Things in banks often call in other things in that bank - I've switched from call to callab with no problems in these instances in the case of functions.
You also need to be careful with images; if something calls a set of images from one bank, and you moved one of those, you'll need to update that code to tell it the new bank to use. In the case of adding new pokemon, I highly recommend Dannye-33's Yellow Gen 2 Sprites Base instead of vanilla pokemon yellow disassembly. All you have to do there for new pokemon images having different banks is to go into their main datafile (such as pikachu.asm) and add the bank on the end! Viola! No more bank troubles.
My Added New Species Turned Into a Trainer!
If you add over 201 species, those over that number will turn into trainers in the wild. Annoying, I know. I believe there is a 'expand past 255 pokemon' project that fixes this and does all the hard work of adding pokemon for ya -wink-, it's for pokered but Yellow is similar so a lot of code, maybe even all, should be portable over. I haven't done this myself though.
My new pokemon turned into an ugly blob! / My pikachu emotion sprite is messed up!
You need to be careful that your image isn't too big or contains too many colors. I recommend a program like gale that can reduce colors to a small palette and then draw with them. What I like to do is duplicate an existing game-friendly image and then just blank it out and draw over that.
-------------
If you want to see some results of this code in action, check out my Yellow hack's screenshots in my hack's thread. Or play the game yourself - it's the first and currently the only hack with an evolving following pokemon, but hopefully with this tutorial that won't stay true for long!
UPDATE:
I've added some extra walking sprites that you can replace pikachu and raichu with. If you are lazy, you can just rename the sprite in question 'pikachu' and put it in the proper folder and it'll work like a charm. Partial credit goes to Dannye-33 for the Persian, Meowth, Eevee, Butterfree, Ghost, Ditto, Zubat, Dratini, Geodude, Fish.
Gyarados's partial credit goes to emimonserrate, who made the sprite I based the walkset on.
There is now a Github that contains the changes I speak of if you want to see it.
-
raichu.png 640 Bytes, 474 viewsToggle Dropdown
-
cycling.png 533 Bytes, 423 viewsToggle Dropdown
-
persian.png 605 Bytes, 420 viewsToggle Dropdown
-
squirtle.png 540 Bytes, 403 viewsToggle Dropdown
-
ballpoke.png 346 Bytes, 401 viewsToggle Dropdown
-
bulbasaur.png 569 Bytes, 400 viewsToggle Dropdown
-
charmander.png 608 Bytes, 399 viewsToggle Dropdown
-
bug.png 570 Bytes, 402 viewsToggle Dropdown
-
meowth.png 612 Bytes, 398 viewsToggle Dropdown
-
fish.png 638 Bytes, 400 viewsToggle Dropdown
-
geodude.png 389 Bytes, 395 viewsToggle Dropdown
-
ghost.png 529 Bytes, 398 viewsToggle Dropdown
-
gyarados.png 529 Bytes, 396 viewsToggle Dropdown
-
eevee.png 517 Bytes, 400 viewsToggle Dropdown
-
ditto.png 406 Bytes, 392 viewsToggle Dropdown
-
sandshrew.png 432 Bytes, 394 viewsToggle Dropdown
-
zubat.png 464 Bytes, 395 viewsToggle Dropdown
-
snake.png 609 Bytes, 390 viewsToggle Dropdown
-
pikachu.zip 91.0 KB, 29 viewsToggle Dropdown
-
raichu_cry_1.wav 78.3 KB, 20 viewsToggle Dropdown
-
raichu_cry_2.wav 79.6 KB, 12 viewsToggle Dropdown
-
raichu_cry_3.wav 54.5 KB, 15 viewsToggle Dropdown
-
Raichu_unhappy.wav 98.2 KB, 15 viewsToggle Dropdown
Evo-Yellow: 151 Evolve Raichu Hack, uses the Yellow Disassembly. Play as girl, ride a pokemon, special/physical, dark/fairy/steel types, new pokemon, gen 2 sprites, evolve Pikachu into Raichu and have them still follow you with new Raichu emotion sprites!
Yellow Hack Tutorial
Fire Yellow - A FireRed Hack & Yellow Remake with Following Pikachu - I am not continuing this until I get a new computer where I can use the latest disassembly. My old one can only run gen I disassemblies.
Yellow Hack Tutorial
Fire Yellow - A FireRed Hack & Yellow Remake with Following Pikachu - I am not continuing this until I get a new computer where I can use the latest disassembly. My old one can only run gen I disassemblies.