Monday, June 9, 2014

Preparing for Battle

It's been a very long time since I've last posted here, but that's mainly because the to-do list in the last post was so long. I finished everything I really wanted to finish, which was all of the Pokemon- and item-related stuff, so battling would only be battling and not worrying about stuff like leveling up. To be fair, I skipped the scripting commands I had planned because I realized they're not as necessary. I dumped the data for wild encounters and trainers (which was annoying, and I'll explain why in a bit), so now implementing encounters is what I'll be doing next.

Wild Encounters
Wild encounters are easy. Dumping the data was extremely simple, especially since I already had ClassicMap loading it. The pre-battle fading is really easy too - fade to black, from black, to white, from white; rinse and repeat a couple times - so those shouldn't give too many issues. I've also figured out (but have yet to dump) the battle transitions, so those should be fun.

Dealing with wild Pokemon encounters is actually quite interesting. Rather than check if you're "on" grass or "in" water, check if rand() % x == 0, and do battles that way, it's a bit more complicated than that. The way the game checks for wild Pokemon is as follows:

-Has it been 3 steps since the last battle? If yes, is the bottom right tile the tileset's grass tile? If yes, is RND < grass encounter rate? If yes, we have a wild battle.
-Has it been 3 steps since the last battle? If yes, is the bottom right tile the tileset's water tile? If yes, is RND < water encounter rate? If yes, we have a wild battle.

Now here is where things get interesting, and why the Missingno. glitch exists. Is the bottom left tile water? If yes, use the water Pokemon. If not, use the grass Pokemon. You can exploit this fact in a couple of places. In the area just south of palette down, surf along the west coast where there is a little bit of land. Even though you're surfing, you'll encounter the grass Pokemon. This is true for any place that has a water encounter rate and grass Pokemon.

So why does the Missingno. glitch occur? When you surf on the east coast of Cinnabar Island, you're in the next map over. This map has a water Pokemon encounter rate, but no grass (Nor does Cinnabar Island). Therefore, it skips loading grass Pokemon. But remember I said the corners it checks for rates and Pokemon sets is different. The game sees you're moving on water, so it uses the water encounter rate, but the grass Pokemon set for what you encounter. When you talk to the man in Viridian City, the game stores your name in the grass set list, which is why your name determines what you encounter. Flying from any map to Cinnabar island will cause its coast to use the last grass set that was loaded.

Long story short, the Missingno. glitch will work exactly the same in PMR, without much effort.

Trainer Battles
So I thought these were going to be a piece of cake originally, since each trainer contains a trainer ID and a Pokemon set. However, the game stores trainer viewing distances and their battle text in places only accessible through scripts. No pointer tables - they're loaded inside of the map's scripts. But fortunately, GameFreak was very consistent in how they loaded trainer headers. They would load HL with the address of the header, and then DE with something else. If they didn't load DE with anything, there would be no trainer headers. I just had to make the dumper detect this and bam, I had a map's trainer header pointers.

That's pretty much all I have to say for battle encounters. Hopefully you learned a thing or two.

Friday, May 9, 2014

To-Do Before Battling

I took a short break from the game and am going to resume work shortly. However, I only planned on everything up to the Pokemon stat menu. There aren't many huge feature categories left, so I need to plan everything out to work better. Why not share it with all of you?

Finishing the stat viewing menu
  • Proper Pokemon default movesets (AKA leveling up)
Using items
  • Gathering a list of what can be used outside of battle and what cannot
  • Potions/healing
  • Rare candies
    • Leveling up
      • Evolutions
      • Move learning
  •  Evolution stones
    • Parsing a Pokemon's evolution type (Fun fact: there is a minimum level requirement to use evolution stones, but they're all set to 1)
  •  Status-curing items
    • Implementing a Pokemon status
      • Poison step handling
      • Fainting
        • Warping back to PC
        • Player money
  • Escape rope
    • Testing if the player is in a dungeon
    • Fade to white
  • Repels
  • EV boosters
  • Revives
  • Ethers
  • PP ups
  • Bicycle
Wild Pokemon encounters
Trainer data
Pokemon- and item-related script commands 
  • Checking what Pokemon the player has
  • Giving the player a Pokemon
  • Checking if the player has an item
  • Giving the player an item
  • Initiating a wild battle
  • Initiating a trainer battle

That seems to be it off the top of my head. Once these features are implemented I should be ready to go for battling. I was going to start with battling, but there was such a large subset of features like leveling up and evolving that needed to be working. I realized they could all be covered by implementing items, which will make battling much faster and easier.

Simulating Lag

Hello, and welcome to the first post on the Pokemon Multiplayer Red blog. I thought about doing an introductory post but scrapped what I had because it gave away too many secrets that cannot be revealed until the game is released! :)

So I figured I'd start on a rather "controversial" topic (in quotes because it's probably the most common thing mentioned but isn't like debated and hushed on the streets), which is in regards to delays and proper timing on things.

Now you obviously know the Gameboy doesn't stand up to the power we have in computers today. You could probably smash a hammer through your case right now and it'd still be able to do more. Not to say the Gameboy is bad on its own, but in all honesty, it was too weak for even Pokemon Red and Blue. Sure, the game was playable, but there are a lot of points in the game that struggle to keep up. Noticeable examples of this are opening the start menu, walking around with other NPCs on the screen, crossing between maps, loading a Pokemon in the stat summary screen, and so on and forth. We can point fingers at GameFreak for some of these things, but ultimately it was because the Gameboy ran at a whopping 4.2MHz, and unfortunately that just wasn't fast enough.

So why does this matter? Well it's this lag that give the games their authentic feel - that feel when you're in a rush and want to view your Pokemon's stats, so you hit the A button 20 times while waiting for things to load. When a menu appears it feels like it's shifted the game's state, like the menu wasn't there before and you had to wait for someone to build it. It felt good and rewarding.

Unfortunately (ironically), our computers are too good. When we need to construct and produce the start menu, bam - it's done in a millisecond. There is no waiting involved, and it feels like it doesn't play as big of a role. The fact that it just pops up instantly seems like you're not creating anything, but rather just bringing it into view as if it was there.

Long story short, the lack of proper delays doesn't make PMR feel super authentic. You can feel it's a clone because everything is super sharp. The answer to this "problem" is to force the game to wait before drawing that start menu. "What's that? You're ready to go right now? Shut your mouth. Sit down and wait 20 frames." is what it really comes down to.

If the answer is that simple - just add some delays - then why is it such a big deal? The big deal is how the engine is programmed. It's made to be flexible and hopefully pain-sorta-lessly be able to be used for second generation. The only way to get delays accurate is to add a bunch of loading modes, which will no-doubt clutter up the Textbox class (which isn't pretty as it is right now). The rest of the project will get uglier with this seemingly-useless code everywhere, and suddenly people will start criticizing my public static friend boolean void c0d1ng sk1llz. Not that the last part matters, but keeping your code clean is like keeping your desk clean. You can get work done, but every time you need to put something down or find something, it becomes increasingly time-consuming, ugly, and upsetting.

In conclusion, I've been working on getting really basic delays working. There is no one-size-fits-all method of simulating lag, but having some exist does really add depth to the game. Isn't that kinda odd? But anyway, until I find a real solution or break down and just add the different types of delays that exist, the game will have some off delays. You don't need to tell me.