Loading...

Top
PFQ Banner

This is PokéFarm Q, a free online Pokémon collectables game.

Already a user? New to PFQ?

Single post in Dev Log 204

Forum Index > Core > Announcements > Dev Log 204 >

Niet [Adam]'s AvatarNiet [Adam]
Niet [Adam]'s Avatar
"Have you tried turning it off and on again?" Sometimes, you just have to stop. Take a step back. Breathe. Ask yourself tough questions. "What am I doing here? What is it I want to achieve? What are my goals, and what will it take to reach them?" So it goes with PFQ/PFNew. What am I trying to accomplish? I have been struggling with this for some time now. Remember that PFNew's initial development started in 2018. Here we are coming up to five full years later and I have very little to show for it. I have ideas - loads of ideas - but not much has been done. Some of that is down to motivational issues, which I have been struggling with for a long time now, but another aspect is the technical side of things. I want to talk about those here. This post will get quite technical. I think it's interesting, but I'm a nerd so... yeah. There's a TL;DR at the end! PFQ is built using PHP and MySQL. Fairly standard for a website, but not really that great for something as complex as a game. I make it work, sure, and when the only tool you have is a hammer, every problem looks like a nail. That doesn't mean it's good. There are many things that very much could be improved, such as the load times of some pages, but not if I keep going with the same hammer. I'm considering different software architectures for PFNew. Lately I have discovered JSON Schema, and I'm very much enjoying it. JSON, short for JavaScript Object Notation, is a format for defining objects in a way that is easy for both humans and computers to read and understand. However, without additional context, these objects could be literally anything. That's where JSON Schema comes in. JSON Schema is basically "JSON that describes JSON". It uses a known vocabulary to define what the format of a given JSON file should be. (There's also Meta-Schemas, which are JSON Schemas that describe JSON Schemas!) The biggest advantage to JSON is that it allows more complex structures than a MySQL database. To give just one example, the base stats of a Pokémon on PFQ have to be stored as six separate "unsigned byte" columns, whereas in JSON they could form a single nested object with the six stats as properties. And there's no real limit to how deep this nesting can go, so long as the Schema permits it. To illustrate the massive difference this can have, let's talk about Evolution. And, of course, when Evolution comes up, you should immediately think of Eevee. Here's how Eevee's evolution data is stored on PFQ:
+-----+------+-----+-----------+ | id | from | to | condition | +-----+------+-----+-----------+ | 144 | 143 | 144 | I:16; | | 145 | 143 | 145 | I:14; | | 146 | 143 | 146 | I:15; | | 147 | 143 | 147 | H;D:1; | | 148 | 143 | 148 | H;D:0; | | 149 | 143 | 149 | F:grass; | | 150 | 143 | 150 | F:ice; | | 151 | 143 | 151 | E; | +-----+------+-----+-----------+
Does that make sense to you? I guess if you really focus you can kinda work out what it does. The first three are probably Vaporeon, Jolteon and Flareon, so that I:16; is most likely "evolves using an item", with the number being the item ID. "H" is clearly Happiness, with D for Daytime. F for Field, E for... affEction? Sure that makes sense. But only because I gave you the context that this is Eevee's evolution data. You'd have to know that Eevee is '143' in the database to start with! Here's the data again, but this time from the updated, JSON Schema-backed file:
"eevee"
: {
// ... (most species data here, omitted to focus on the evolutions)
"evolutions"
: [{
"target"
:
"vaporeon"
,
"conditions"
: {
"item"
:
"water-stone"
} },{
"target"
:
"jolteon"
,
"conditions"
: {
"item"
:
"thunder-stone"
} },{
"target"
:
"flareon"
,
"conditions"
: {
"item"
:
"fire-stone"
} },{
"target"
:
"espeon"
,
"conditions"
: {
"happiness"
:
true
,
"timeofday"
:
"day"
} },{
"target"
:
"umbreon"
,
"conditions"
: {
"happiness"
:
true
,
"timeofday"
:
"night"
} },{
"target"
:
"leafeon"
,
"conditions"
: {
"field"
:
"grass"
} },{
"target"
:
"glaceon"
,
"conditions"
: {
"field"
:
"ice"
} },{
"target"
:
"sylveon"
,
"conditions"
: {
"affection"
:
true
} }],
// ... some more data down here
}
Isn't that so much better to read? And understand? And work with? Of course... the big downside is that I actually have to translate PFQ's mess of data into this clean new format, but it's going well so far and it's allowing me the chance to rethink how some things are implemented. Such as, let's say, Shellos. On PFQ, Shellos hatches into either its East Sea or West Sea form depending on which side of your Party it is in when you hatch the egg. This is done by interrupting the Egg Hatch code with an additional hook, "if the species is Shellos, check its position in the party and swap its form if necessary". This is a very "imperative" style of programming, and while there's nothing wrong with that in theory, in practice this makes it very difficult to change or update things if necessary. This was fine originally, but as more Pokémon get added and more special cases are needed, it can become a real hassle to find where a particular case is actually handled. Contrast this to how it is handled in the new JSON format:
"shellos"
: {
// ... some data
"hatch_trigger"
: {
"type"
:
"east-west"
,
"east"
:
"east-sea"
,
"west"
:
"west-sea"
},
// ... more data
}
This more "declarative" style means that the "special case" is part of the species' data. There's still going to be a hook in the hatching code, but rather than specifically checking for Shellos, it will ask "does it have a hatch_trigger?" and perform some action if so. Other hatch triggers I've defined so far include "random-form" (for Unown that don't have Unown parents to pull inheritance from), "population" (for Basculin Red/Blue-Stripe) and "environmental-variation" (for Maravol, and as an evolution trigger for Vivillon). This makes things much easier to maintain and understand, which is a big problem that PFQ currently has. Speaking of evolution triggers, since they got casually mentioned above, those are handy for dealing with special cases too! Shedinja becomes a "spawn-clone" trigger with a few "overrides" to change its gender to Genderless and such. This means that if we ever wanted to add a Fakemon that has a Shedinja-like phantom, we totally can do that on PFNew without adding any further code - just declare its properties on its data. On top of that, I can make use of this new and flexible file format to simplify a lot of things. On PFQ, "Lefty Delphox" is actually handled as an entirely separate species, but with completely nulled-out data except for its name and sprite. That seems so wasteful! In the new file, it is simply an "alt-sprite" on the main species. Rewriting the data like this has also led to some great new ideas for PFNew as well: - Vivillon patterns can be made hereditary, allowing players to hunt all of the Shinies if they want to as they'll only need to collect a suitable parent of each pattern from other players. - Genesect will be able to use its held Drive as an alternative attack type in Spars thanks to a new "additional-type" property on its forms. - Formes in general are simplified into just one entry. For instance, Alolan Rattata is considered an alternative form of Rattata, with its breeding conditions declared and handled appropriately. All alternative forms count as a single Dex entry, but are still registered independently so that you can be as completionist as you want without needing every single form to complete the game. On that note, "Custom Sprites" can just be event-reward alternate forms as well! - Similarly, Unown will be a single Dex entry. As will Silvally, Arceus, and even Saiyan Rattata! Honestly this whole thing is just so much nicer to work with and I haven't even finished setting it up yet. I'm already loving it, and the ideas that it has led to. Nidoran will be able to have its different stats for males and females again! If we decide to add actual movesets for some more advanced battling system then Meowstic will be able to have its gender-specific movesets too. It's all there, all defined in this file! Of course this is only really possible because features are being planned out in advance, unlike PFQ which really just grew like slime mould. (If you haven't seen slime mould growth patterns, by the way, they actually look quite impressive, if a little gross!). Features like Fusion, which didn't exist when PFQ was first developed, can be formally introduced as data elements. The Kyurem involved could then have a "fusion partner" item in its data to point to the Reshiram/Zekrom it is fused with. For Calyrex this would provide a much cleaner way to handle its various Rider forms that PFQ has (eg. Shiny Calyrex riding an Albino Spectrier). TL;DR I'm changing the format that data is stored in for PFNew, from a rigid table-like structure to a flexible object-based one. This will massively simplify how the Pokédex works on PFNew, while allowing a greater flexibility in how players choose to approach 'dex completion. Exciting times! My motivation is flowing at last, and although this does mean starting PFNew over again, this should be the one that actually takes off, because it is being planned properly. I hope. XD Discuss!
Clip from Pokémon anime, re-lined by me
-- OMNOMNOM!
Featured story: Injustice Feedback welcome!
© PokéFarm 2009-2024 (Full details)Contact | Rules | Privacy | Reviews 4.6★Get shortlink for this page