Discuss Scratch

OrcaCat
Scratcher
1000+ posts

Pokemon Battle Engine Help

Hello,

I'm working on a Pokemon game called Pokemon Apple Red. I've figured out how to do almost everything you would find in a Pokemon game, all except the most important thing: the battle.

Pokemon battles have a simple concept but are very complicated. If you are unfamiliar with Pokemon, here is an explanation.

Here's some pseudocode I wrote:
define attack
Determine Enemy attack/switch/item
Determine faster Pokemon (using speed stat)
If doublebattle
Choose which Pokemon to attack
Switch Pokemon/use item?
Else
Faster Pokemon attack
Fainted? then switch
Switch Pokemon/use item?
Else
Slower Pokemon attack
Fainted? then switch
If all enemy fainted
do stuff like looser crying
finish battle
If all player fainted
finish battle
do stuff like whiting out

define choose action
If attack button chosen
Show attack menu
Set Useraction to chosen attack
attack
If Pokemon button chosen
Show pokemon inventory (I'll figure it out later)
if switch chosen
attack
If Run button chosen
If battle type == wild
test run
else
type(There's no running from a trainer battle!)
If Item button chosen
Show item inventory (I'll figure it out later)
If Pokeball chosen
set action to Pokeball
attack

Play animation for Enemy and Player
Show menu
repeat until battle finished
choose action
If double battle
choose action
But the problem is, the moves are reeeeaaaalllllyyyy complicated. They're very diverse. Some moves attack for 2-3 turns. Some require you to recharge. Some inflict status problems. Here's a list of all moves. I only want the first 165. Click on them to see what they do. Here's the formula for damage

My brother told me that JSON would work well for this. But to make it in Scratch, I could use 165 ifs…

But is there a more efficient way to do this? I really don't care if it's complicated.


shadowmouse
Scratcher
100+ posts

Pokemon Battle Engine Help

What about making a list of all the moves and what they do (try to structure it as an array). When a pokemon learns a move it defines the command move 1 as to how many turns it will last, what power e.t.c. Each part (turns, power…) would have a variable. The actual command is defined stright away but if upon learning, these variables are set then this should do the trick. Sorry if this is vague, I've played pokemon all my life and some of it still baffles me.

I'm making a game! It's a old-metroid/mega man esque side scroller/shooter. If your interested in anything from drawing to sounds, please message on one of my projects!
Wyrlwynd
Scratcher
14 posts

Pokemon Battle Engine Help

The large majority of Pokemon moves are single turn moves. Create a variable that designates a move by its # of turns it runs. Create a script for single turn moves (# of turns = 1 for example) where you pull the power and accuracy from a list of all of those moves and their info. There are 2 turn charging moves like Solarbeam and so on. Bundle those in a list and create a script (# of turns = 2 for example) that handles those types of moves. The Hyperbeamish ones that attack and need to recharge. Generally moves fall into groups with others of different types. And so on. By frontloading the data on move power and accuracy and effect into some pretty long lists (or multiple lists whatever floats your boat) and then bundling them by similarity, you could reduce the number of if thens.

mitchboy
Scratcher
1000+ posts

Pokemon Battle Engine Help

I would recommend making lists of the “special” moves (as in ones that can cause status problems, last for x turns, etc.) and have the move used as a variable, then check if [list] contains (move). Then, for certain lists like the status problems, you will need another list to go with that to determine the type of status problem it could cause.

Capsicum annuum.
OrcaCat
Scratcher
1000+ posts

Pokemon Battle Engine Help

mitchboy wrote:

I would recommend making lists of the “special” moves (as in ones that can cause status problems, last for x turns, etc.) and have the move used as a variable, then check if [list] contains (move). Then, for certain lists like the status problems, you will need another list to go with that to determine the type of status problem it could cause.
Nice idea. I think I'll use this.


Wes64
Scratcher
500+ posts

Pokemon Battle Engine Help

the important thing about making any battle system is to ensure it isn't rigidly structured. you should only ever have one single script for any given function. damage should be dealt by the same script, stats raised by a different script. this way any series of actions is possible. this is the way the Spectrum battle system works.

it is structured like this:

Queue - one sprite controls how data is chosen. scripts for outputting lists of possible actions and choices go here. once actions are selected, they are added to a “queue” list and the monster speed is added to an “order” list. once the queue has defined actions for each battler, either through user input or enemy AI, the queue is rearranged according to the monster speeds in the “order” list.

queue data is structured like this: s.t.a.n

s is the user (self) that defines who is using the action. this is a number 1-6. (in your case it would be 1 or 2).
t is the target that defines who the action is done to (same numbers)
a is the action (i.e. attack, defend, technique, item)
n is any number that defines the action (for example, if the 37th technique is being used, it would be 37)

Exec - this is the sprite that reads queue data and runs the battle system. Scripts work like this:

1. unpack the queue data into variables (self) (target) (action) and (argument)
2. apply any pre-turn effects (for example if the user is dead, incapable of moving then the turn is skipped. if the target is dead, then the target is redirected)
3. broadcast to another script according to the action. attack has its own script, defend has its own, technique has its own, etc. This script will control the action.

4. i know pokemon has extensive strategy. I use a “cache” sprite to store all the data so there aren't too many global lists. in this step, if a cache is used, the data for the technique number is retrieved so the game knows what actions to take.

Cached technique data is like this: power, cost, priority, and magic/physical are all in their own lists. the effect is stored as a chain of data like the queue data. it is in the form t.c.a.n where t is the target (i.e. all enemies, one enemy, yourself, your team). c is the “class” (i.e. status effect, stat increase, etc), a is the defined action (i.e. raise speed or inflict paralysis) and n is the number (i.e. 60 for a 60% chance or 2 for raise stats 2 - each script will process this differently).

5. broadcast to another script according to which class the technique is (stats up are all in one script, status conditions in another, etc)
6. special conditions are calculated and applied. in the “Exec” sprite, each monster is referred to as the numbers 1-6 (which is why self and target are those numbers) and all stats are kept in lists (attack, attack boost, hp, max hp, etc). each number corresponds to a spot in a list. so if “2” is the target and the effect is to raise stats, the second item of the “attack boost” list would be increased.

7. if damage is dealt (tech power > 0) then it is calculated by one script using “item self of attack” and “item target of defense” list reporters. the game checks to see if anyone died, won or lost. EXP is awarded.

8. since the queue data is in order, the script moves on to the second item in the queue and returns to step 1.

this might make no sense, but it's the way I did it. in summary, make sure your data is organized. never script the same function twice and keep data flowing in an orderly way so that scripts are only running when they're supposed to. keep all the data you need for the battle in lists in the battle system so you don't have to recalculate it all the time and make sure only one script does each calculation. make sure only one script controls each function.

the worst thing with projects of this scale is getting lost in your own scripting. keep it simple, clean, organized, and most of all malleable and editable so you can add more things easily.

i cannot say this enough times - never have two scripts that have the same thing built into them! one script for one calculation, no matter how irrelevant it seems. you don't want to have to change 10 instances of a calculation in your scripts.

good luck!
-Wes

ps - im sure you'll have specialized questions so feel free to ask. the hyper-beam effects and such can be achieved simply by having a list for all of player 1's ongoing effects and for the other enemy as well. if the list contains “charging” then the turn is skipped and “charging” is deleted from the list, or if it contains “poison” then poison is applied.

Last edited by Wes64 (July 20, 2013 21:01:01)


Using Firefox 46.0.1, Flash plugin version 21.0.0.242, and Windows 7 Professional.
A computer does what you tell it to do, not what you want it to do. - Murphy's Law
OrcaCat
Scratcher
1000+ posts

Pokemon Battle Engine Help

Wow, thanks Wes!


Powered by DjangoBB