Posted: Sun Mar 30, 2003 4:32 pm Post subject: [Tutorial]How to Make an RPG in Turing
How to make an RPG in Turing - Dated March 30th, 2003
This guide will help you through all the steps of creating an RPG. Be aware that in order to actually allow the user to "roleplay" their character, the better the experience, although this requires a lot more coding than a simple hack and slash game. Be warned, an RPG is very difficult to code, and will take many weeks, and months, or even years if you want it to be very well done.
Things to Know Before You Start
When making the RPG, make sure that you have knowledge of the following Turing concepts, and how to use them:
Displaying Text (Obviously)
Collecting Variables and using them
If statements (Very important)
Reading and Writing to/from a file (If you use saving)
Functions and Procedures (VERY useful for repetitive processes)
Processes (For music, or timers)
Arrays (For many types of 1 variable. i.e. items)
Loops (Very important in an RPG! Know conditional and counted loops)
Random Number
That should cover the basics. If you decide to make a more complex RPG, you may require other things, such as modules, etc. If you do not have sufficient knowledge of these concepts, it is not recommended that you make the RPG, until you have learned them, as this will make your life much harder.
A recommended idea is to play an RPG thoroughly, and explore the game, until you get the feel of how an RPG is made. The more you know about an RPG, the easier it will be to make your own.
About this Tutorial
This tutorial will cover many commands of Turing that you should know, but read them anyways, because their uses may help you when you want the RPG to do a specific task.
RPG Creating Concepts Covered
The Overall RPG Experience
Turing Concepts
Displaying Text
Collecting Variables and using them
Naming Variables
Reading/Writing from a file
Functions and Procedures
Processes
Loops
Arrays
Random Number
Properly Accepting User Input
Elements of an RPG
Readme File
Collection of Data
Damage Range
Gender
Races
Classes
Stats
Battle System
Attacking
Magic
Resistances/Weaknesses/Immunities/Absorption
Abnormal Status
Running Away
Other Notes on Battle System
Items
Experience Chart
Other Experience Charts
Making your RPG better
Testing
Balancing
Improving
Final Notes
The Overall RPG Experience
Once you have decided that you want to code your RPG, you need to ask yourself a few questions:
Who is playing this game?
A very important aspect of creating an RPG is the audience. Do you intend the game to be played by new gamers, or hardcore RPG gamers?
If it is the former, you want to keep it simple, and easy for the user to understand. The RPG must be simple, and easier for them. Stick to the basic elements of an RPG, like stats, equipment, spells, items, etc. You do not need to include things like quests, puzzles in rooms, etc.
If it is the latter, you are in for a tough time. Although it is impossible to make an RPG in Turing that compares with famous games such as the Final Fantasy series, it is still possible to make one that is enjoyable to all, including the hardcore RPG gamer. You need to give the user something that will keep him/her playing, such as quests, a more complex character building system, and many elements that you can see in other RPG's. As recommended above, if you have played many RPG's, it should not be too difficult for you to look for new things to add.
Is this for a project, or just for fun?
Another important issue to address. The main issue discussed here is time. For a project, time is limited, and your main priority is to finish. If it is for fun, the finishing is likely not a possible aspect at all, because if it's for fun, you have as much time as you want to work on it, and improve it multiple times. For a project, you will likely have to stick to a simple RPG, that sets the user straight into action immediately, while an RPG made for fun can delve into the more complex aspects of an RPG.
How much control do I want to give the user?
This is closely related to the first question. You want to know how much control of their character growth you want to give. For a simple RPG, you should control their character growth, such as preset stats at certain levels for example. A more complex RPG should allow a user to customize their stats, choose their own classes, choose their own magic, and for a real challenge, emotional growth, which will allow the user to develop a character's personality that can affect the outcomes of certain events.
The above questions will help you set a guideline of how to make your RPG, and will set limits on how complex you want it to be.
Turing Concepts
Note: The following sections are not how to use them in Turing, but how to use them when coding your game. If you don't know how to use these commands, please look it up somewhere else.
Displaying Text
This is a very easy, and yet very important aspect of an RPG. You need to be able to have a way to communicate with a user, and have the user communicate to the program. Otherwise, there is no interaction, and that would make an RPG very boring. An example of how to display text is:
put "Welcome to my game!"
Simple, and yet effective. If you want, you may opt to use text effects also. See the other tutorial for text effects.
Collecting Variables And Using Them
Variables are the backbone of an RPG. Without them, the game is virtually impossible to make. You will need variables for storing stats, character details, spells, skills, items, monster data, just about anything the user does. You essentially need about 4 types of variables:
String (Deals with text variables, such as names, spells, items, etc)
Int (Stats, hit points, anything that needs a number)
Real (Decimal numbers, which are used in percentages, etc)
Boolean (Can be omitted, but will make certain comparisons easier)
String Variables
The string variable is very easy to use. It stores text for later use. You can use this in a variety of ways, such as comparing the input of a user to a set of strings that the game already has inside it. It can be used in character names, names of skills/magic/items/monsters, and a lot of other uses.
Int Variables
This variable can be used to store stats, item amounts, gold/money, or anything that requires a number.
Real Variables
This variable is a little harder to use. This variable is needed when you want to calculate percentages. Percentages also deal with random numbers, so make sure you know how to use them.
Boolean Variables
This is an optional variable, for values that you need to store when there are only 2 possibilities, yes/no, 0/1, or however you want to arrange it. You can use this variable in situations such as enabling/disabling music, whether or not a skill can be used, whether or not a level has been gained, etc.
Naming Variables
Naming your variables is simple. Make sure you name all of your variables according to it's purpose, as this allows you to be able to differentiate the different variables a lot easier. It's also recommended that you use a commend (%) besides each variable that tells you what it does, in case you forget.
Good Variable Name: character_name
Bad Variable Name: cn
Reading/Writing From a File
If you wish to include a saving feature in your game, read this section, otherwise, skip it. But think about it, what good is an RPG, if you can't save? So it would probably be a good idea to include some sort of saving feature. First of all, you need to come up with a list of variables that are needed for future use, and those that are used for temporary purposes. For example, in the following list of variables,
Name of Character
Hit Points
Answer from user
You would save the first 2, as they are important to the operation of the game. The answer from the user is still important, but is not required when saving, because it is just used to temporarily store what the user enters. Let's say you want to save the name of a character, you would use:
code:
var stremout : int %Does not need to be set
var pathName : string := "save.sav" %The name of the file to be saved
var character_name : string := "Azndragon" %The variable to be saved
open : stremout, pathName, write
write : stremout, character_name
close : stremout
Using the write command instead of the put command allows you to partially secure your save file. If you use the put command, a user can open your save file in a text editor, such as notepad, edit the values, and save it. If you use the write command, and the person edits and saves it, Turing will not recognize the values, and will not work properly.
Loading a variable is similar to saving it:
code:
var stremin : int %Does not need to be set
var pathName : string := "save.sav" %The name of the file to be loaded
open : stremin, pathName, read
read : stremin, character_name
close : stremin
If you used write to save the file, you use read to load the file. If you used put to save the file, you use get to load the file.
By using the two above examples, while combining multiple variables in your save file, you can make a saving system, and therefore, allows the user to quit your RPG, and play it again later.
Functions and Procedures
If you are doing certain actions multiple times, Functions and Procedures may be the answer. Let's say you want to have a battle, and it's 500 lines long. If you want to have another battle somewhere else in the game, you would have to paste the same 500 lines somewhere else in the code, which is a waste of space. The alternate method is to use a procedure to load the battle. Start off with a "procedure battle", then paste your code, then put a "end battle" and every time you want to load a battle, just use the code "battle" and it will automatically execute the battle.
code:
procedure battle
[insert battle code here]
end battle
put "An imp attacks you!"
battle
[pointless events here]
put "A pack of wolves attack you!"
battle
Functions are a lot more complicated. Functions allow you to do certain operations with a parameter to be used within it. For example, if you want to collect gold, use:
code:
var total_gold : int := 500
function collect_gold (gold : int) : int
total_gold := total_gold + gold
put "You now have ",total_gold," gold."
end collect_gold
collect_gold (500)
This executes the collect_gold function, and the brackets are around the variable that is to be added to the gold amount. In this case, 500 gold is added, and the end result is 1000 gold.
Processes
Processes are mainly used for playing music. You make a process, insert the music file in it, and end it. Anytime you want to play the music, you use "fork [process name]", and the music will play in the background.
code:
process play_music
Music.PlayFile (music file location)
end play_music
fork play_music
This will have the music play in the background.
Loops
Loops are very important parts of an RPG. They allow you to repeat many functions of the game. For example, you could use them to repeat battle processes until the monster or the player is left with 0 or less HP. They could also be used in combination with arrays for optimum efficiency, which is explained in the next section. There are 2 types of loops; counted, and conditional.
Conditional Loop
This loop just repeats itself over and over, until a condition is met, by using the command "exit when [variable] [operator: <, >, etc] [value]" inside the loop. For example:
code:
var gender : string
loop
Put "What is your gender?"
Exit when gender = "male" or gender = "female"
end loop
put "You are a ",gender,"."
Counted Loop
These types of loops repeat for a set number of times, whether it be twice, or 50 times. The power of these loops are used effectively in arrays, and can also be used when dealing with commands that have to executed more than once. Examples of counted loops are in the next section.
Arrays
Arrays are useful for when you want to have multiple variables with the same name. An example would be items. Using item1, item2, item3, item4..item100 is a very time consuming operation. Instead you would first declare the variable as:
code:
var item : array 1..100 as string
This will create 100 variables under the variable name of "item". You can now call on these variables using item (1), item (2), item (3), item (4) .. item(100). Let's say you want to set all items as potions. Instead of using item (1) := "Potion", you can combine the array with a for loop for maximum efficiency:
code:
var item : array 1..100 of string
for i : 1..100
Item (i) := "Potion"
end for
With those simple lines of code, all 100 item variables are now potions.
Now look at this:
code:
for decreasing i : 120 .. 1
if item (i) = "Potion" then
item (i) := "None"
exit
end if
end for
The first thing that you may notice is that it has the word "decreasing" in it. This tells Turing that the numbers in the counted loop are going backwards instead of forwards. This is then used to search for an item called "Potion", and change it to "None". When this is done, it will automatically exit the for loop, therefore completing the process.
Random Number
Random numbers are very useful when calculating percentages, because percentages are based on probability. If something has a 35% chance of happening, you can simulate that with a Rand.Int (1, 100) command. So if you want to use this in your game, and you wanted to give the user a 35% chance of winning you would use:
code:
if Rand.Int (1,100) <= 35 then
put "You win."
else
put "You lose."
end if
The key element here is the >=. Why is that used, instead of <, >=, or >? Let's look into this in more detail. When something has a 35% chance of happening, and there are 100 numbers, the following numbers are winning numbers: 1,2,3,4,5,6..35. Any number from 36-100 is a loss. So if the random number is less than or equal to 35, the condition is met, as shown in the above code. With this system of code, you can simulate any combination of percentages as you please.
Now, for a more complex function of random numbers, consider this. What if you have a skill called Double Attack, that has a 5% chance of working for every skill level you have? How would you do it? Well, the answer is slightly more complex:
code:
var skill_level : int
if Rand.Int (1,100) <= skill_level * 5 then
put "You use Double Attack!"
else
put "Nothing happens."
end if
Properly Accepting User Input
As many of you are aware, Turing is very picky when it comes to caps in input. This is easily seen when Turing will not properly read when a user types in YES, when the programmer wants the user to type in yes or Yes. The solution to this can be solved by using a simple function that converts a text string into pure caps, where it can then be easily accepted by Turing.
function caps (word : string) : string
word2 := ""
for i : 1 .. length (word)
if ord (word (i .. i)) > 96 then
if ord (word (i .. i)) < 123 then
word2 := word2 + chr (ord (word (i)) - 32)
else
word2 := word2 + chr (ord (word (i)) + 0)
end if
else
word2 := word2 + chr (ord (word (i)) + 0)
end if
end for
result word2
end caps
By using "caps(some word)", this function will convert it into "SOME WORD". Now say if you use an if statement after this, the pure caps allows the if statement to pick up on any variation of the string entered. Of course, it will not pick up bad spelling, so if you suck as spelling, too bad for you.
Now that you have the basic Turing concepts, it's time to deal with the elements of an RPG.
Elements of an RPG
Note: The following sections are optional, and you may choose to omit them when making your game.
Readme File
An important aspect of making an RPG is making sure that the user can use it properly. Sure, you know everything, but when someone else runs it, chances are that they will not see the code, and will most likely be clueless as what to do. Readme's do not have to be in-depth; just give the user enough information so that they can play the game correctly. Some things you might want to include in your readme file would be:
Controls
Processes of Game
Explanations of Various Elements of the game (spells, monsters, stats, etc)
Collection of Game Data
When making an RPG, especially the more complex ones, it would sometimes help to make a bunch of Word files, or something along the lines that stores all data in the game. In this case, the data should include things such as formulas, item names, item actions, monsters, storyline, everything about the game that could be used as a reference guide, because you never know when you forget what item does what. Obviously, you would not distribute it when you release the game, or else the other users will know basically everything about the game.
Damage Range
An important component of an RPG is damage. Damage is what kills the enemy and the player. There are generally 2 types of damage ranges:
D&D Style - Usually damage is about 40 or less for a strong character.
FF Style - Depending on the FF game, damage caps at 9999
Of course, you can make your own, but damage needs to be calculated according to stats, and enemy HP should not be too difficult in relationship to the max damage. For example, if a strong attack in your game is 50 damage, it would not be fair to the player if a boss has over 10000 HP, because the damage does not fit the HP value. 1000 HP would be a more realistic amount.
Gender
This is usually a preference setting for many games, but sometimes you may decide to give certain bonuses and penalties to certain genders. This should pretty much be self-explanatory, so I don't think I need to go into much detail here.
Races
Races can be used in the same manner as Gender.
Classes
Classes can be used in the same manner as Gender. Keep in mind that classes should have an obvious relationship with the stats that you will create.
Stats
For most games, stats are the backbone of a character's strength. If not, they are still a crucial element in battle. You should try to make stats that reflect the corresponding classes. For example, if you have a Fighter class, you need some sort of Strength or Power stats. Spell casters should have Intelligence or Wisdom. Be sure to balance the stats so that one stat is not too powerful over another. Some suggested stats to use are listed below. Remember, some stats may seem the same, but may have different effects based on the type of RPGs you have played in the past.
Note: The following sections of the battle system require extensive knowledge of commands such as arrays, functions, procedures, and being able to create multi-step formulas. The following sections should be skipped if your battle system is based on random numbers instead of stats. A complex battle system is probably one of the hardest components to make, so do not expect a good battle system in a few minutes. If you do not have the required knowledge, a simple battle system based on random numbers can and should be used.
Battle System
The most exciting part of an RPG is usually the battles. Battles are supposed to be fun for the user, and is usually required to become stronger or to advance the plot. A battle system will use the loop command extensively, and procedures and functions would really help. The basic form of a battle system should be
Ask user for command
Choose target
Command is done
Enemy may take damage
Enemy loses HP.
Enemy attacks, player may take damage
Player loses HP.
This process is repeated until either the monster or the player's go below zero.
Asking User for Command
This should be pretty easy. You give the user a list of commands, and store their answer as a variable. However, you may also want to display vital information such as HP, or something similar to it, and MP, or something related to that. Things like gold amount would not be useful to know in battle, unless you had some sort of skill/magic/etc that uses gold as part of a damage formula.
Choosing Target
If you want to have multiple monsters in battle, this should be used. If not, skip this section. When choosing targets, remember to give the user an accurate listing of the monsters in battle, and make sure that if a monster is killed, that it will not be shown as a target. You can do this by using a boolean variable, such as monster_dead. If that condition is true, the monster is dead, and will not be shown. If it's alive, the condition will be false, and it will be shown.
Command being Used
The different commands are explained below, and you should give the user plenty of choices to do, to give them more customizability in their battles.
Enemy taking damage
After commands such as attacking, and casting spells, you will need to display the damage, so the user knows what's going on.
Enemy losing HP
This action can simply be done with 1 line of code:
enemy_hp := enemy_hp - damage
Enemy Attacks
This is slightly more complex. There are 3 ways to code a monster.
Pure Attack
Pure Magic
Combination
The first 2 are not that hard. The coding is similar to the one of player attacking/casting magic, you just need to reverse some values. Instead of using player intelligence to calculate spell attack, it is now used as spell defence, since the player is on the recieving end of the spell.
The more complex method of enemy attacking is Combination. Combination enemy attack can also be divided into 2 methods:
Random Action
Artificial Intelligence
Random Action simply uses Random Integers to do random actions, such as a random integer to select attack/magic, etc. This can be a problem with magic casting, because casting random magic spells does not seem to be a good idea, due to the large sections of code needed, so melee monsters should just use random actions. The ideal method of magic monsters should be AI. You should code an AI that does certain actions according to certain actions in battle. For example, if the monster has Max MP, then they should not cast some sort of healing spell. If the monster "sees" that the player is absorbing a certain element, the monster should not cast that spell anymore. If the monster does not have enough MP for a spell, then they will not cast it. Setting up an AI takes up the most code, but the end result is a more realistic monster.
code:
if monster_hp / monster_maxhp * 100 < 100 then
cast_spell := "Fireball"
else
cast_spell := "Cure"
end if
This code states that if the monster is below 100% of HP, it will cast fireball. If not, then it will cast Cure. Of course, this is not fair to the player, because the monster will keep on healing itself, so it's up to you to balance the AI and make sure that the challenge does not become impossible.
In Summary:
Pure Attack - Simple code for melee monsters (will only attack, predictable)
Pure Magic - Simple code for magic casters (will only cast magic, predictable)
Combination - Random Action (random actions such as attacking, casting, etc)
- AI (attack/cast spell, depending on certain battle conditions)
Melee Classes - Pure Attack (basic code)
- Pure Magic (monster is almost useless)
- Random Action (attack, will cast occasionally)
- AI (attacks, will cast spells when necessary)
Magic Casters - Pure Attack (weak monster; magic casters should not attack)
- Pure Magic (casts all magic, can be easily beaten with Reflect Magic)
- Random Action (can do both at random, may cast useless spells once in a while)
- AI (ultimate option, gives mage a command based on battle status, will not cast useless spells)
Simply put, if you have the time, AI is the best option!
Player Loses HP
Back to the basics. Almost exactly the same as the enemy losing HP.
player_hp := player_hp - damage
Adding EXP
At the end of battle, experience should be added to the character's exp. The code should be something along the lines of:
code:
exp := exp + monster_exp
Be sure that you set the monster's EXP before battle. Make sure that the EXP corresponds to the enemy's difficulty.
Levelling Up
Let's say you have a level 1 character that needs 10 EXP to level up. At the end of battle, you would use something like:
code:
if character_level = 1 and exp >= 10 then
character_level := 2
exp_needed := 25 - exp
end if
This means that a level 1 character with over 10 EXP will move up a level, and the exp needed for the next level is 25 - minus his/her current EXP. Now, for a level 2 character that needs 25 exp to level up, you would use:
code:
if character_level = 2 and exp >= 25 then
character_level := 3
exp_needed := 40 - exp
end if
Gaining Gold/Items
Gaining gold is a simple line of code:
code:
gold := gold + enemy_gold
Gaining items is a lot more difficult. Make sure that the item addition is added only once, and if you are using a counted loop with an arary, make sure you use the exit command to leave the counted loop so you don't end up with duplicate items.
The following sections deal with formula calculations. Math skills are not really necessary, because formula calculations should be simple. Keep in mind that formulas are usually multistep, so make sure you can follow what your formula can do to help you test it. The formulas below are based solely on stats. Factors such as Elements, and Abnormal Status are not included, and will be covered later. Also, for simplicity of the code, declaring variables has been ignored. If you wish to test the code yourself, all variables are usually integer, with a few exceptions.
Attacking
There is virutally no way you could make an RPG work without the basic attack command. In most RPGs, this is your only choice, until you can be higher levelled to learn the spells, or for some classes, this is the ONLY way to fight. Damage should be based on the following factors:
Player Level
Player Strength or equivalent stat
Player Weapon
Enemy Level
Enemy Defence or equivalent stat
Enemy Armor (if applicable, such as human enemies)
However, you may also wish to have a separate formula just for calculating whether a hit is even successful or not. A check to see if the attack hits the opponent could be based on:
Player Level
Player Dexterity or equivalent stat
Player Weapon
Enemy Level
Enemy Agility or equivalent stat
Enemy Armor (if applicable)
A simple formula for accuracy check could be as follows:
code:
if (player_level + player_dexterity + player_weapon_chancetohit) >= (enemy_level + enemy_agility + enemy_armor_chancetododge) then
[insert rest of damage code]
else
put "You miss the enemy!"
end if
Of course, formulas may vary, but that's just a simple accuracy check. If the player misses, the battle goes onto the next step. Otherwise, the damage should be calculated. First step, you need to calculate the absolute maximum damage the player could do against an enemy with 0 defence. A simple formula could be
A level 10 character with 50 Strength and has a weapon power of 85 could do a maximum damage of 5100. Of course, you do not want the damage to be 5100 ALL the time, as the damage gets predictable. A way to solve this is by using random numbers.
This calculates damage, and adds up to any number from 1 to 5% of the initial damage as extra damage. If the base damage is 500, the extra damage could be anywhere from 1-25 extra damage. This will vary your damage, and will prevent it from becoming too predictable.
Once maximum damage is calculated, you need a method for damage reduction. You could add up all the enemy defence values and subtract it from maximum damage to get the final damage.
However, a problem arises with low levelled characters. An enemy with more than 0 defence could block a large portion of the characters damage, or if the character is a low-level magic caster, the damage could be completely blocked.
How can this be solved? A more advanced formula could be damage reduction by ratio. Lets say the base attack power (after calculations) is 10 above the base enemy defence (after calculations). Under the simple formula, this is a result of about 10 extra damage.
However, using ratios, this situation could a lot different. Note: The % difference is calculated using ( ( (bsattack / bsdefence) * 100) - 100)
Base Attack Power: 11
Base Defence Power: 1
% Difference: 1000%
Base Attack Power: 510
Base Defence Power: 500
% Difference: 2%
From a gamer's perspective, who do you think should recieve more bonus damage? The answer is obvious; player 1. The first player has obviously trained his character far above the enemy stats. The second character is also very strong, but has not surpassed the enemy as much as player 1, even though they both have 10 higher attack than the enemy defence.
What if the enemy has higher defence than the player's weapon power? Using the simple formula, the damage would be in the negatives, which would not be possible, and if the damage is 1, would make the battle almost impossible to win. Again, using ratios and % differences is the solution. Taking the previous values and reversing them gives a much different result. Note: % Difference is calculating using ( ( (base_attack / base_defence) * 100) - 100)
Base Attack Power: 1
Base Defence Power: 11
% Difference: -90.9%
Base Attack Power: 500
Base Defence Power: 510
% Difference: -1.9%
Player 1 is obviously far behind the enemy's stats, while player 2 is slightly behind, but not as much. Again, in both cases, the stats have a difference of 10.
With the % difference in place, the formula is simple:
if Rand.Int (1,100) <= critical_chance then
[critical hit]
else
[normal damage]
end if
If the critical chance is 33, then the number has to be 1,2,3..33 to deal critical damage. If not, damage is normal.
And that's it! The damage calculating is done! An example of an attacking code could be:
code:
if (player_level + player_dexterity + player_weapon_chancetohit) >= (enemy_level + enemy_agility + enemy_armor_chancetododge) then
damage := (player_level + player_strength) * weapon_power
damage := damage + Rand.Int (1, damage * 0.05 div 1)
base_defence := enemy_level + enemy_vitality + enemy_armor
if base_attack >= base_defence
bonus_damage := damage * ( ( (base_attack / base_defence) * 100) - 100)
damage := damage + bonus_damage
else
reduced_damage := damage * ( ( ( (base_attack / base_defence) * 100) - 100) * -1)
damage := damage - reduced_damage
end if
if Rand.Int (1,100) <= critical_chance then
damage := damage * 2
put "You land a critical hit, dealing ",damage," damage!"
else
put "You have dealt ",damage," damage!"
end if
else
put "You miss the enemy!"
end if
Remember, this is just a sample. Keep the damage limits, stat limits, weapon powers, armor powers, enemy defences, etc. into account when making your formula. You will most likely have to refine the code a little, so change some values or parts of the formula when something is not right.
Magic
If you plan to have magic in your RPG, this section is very important. Magic has the primary purpose to damage the enemy in battle. In order to calculate damage, it should be dependent on:
Your magic power
Your level
Enemy's magic defence
Enemy's level
You can also cover resistances/weaknesses, etc, but that will be covered in the next section. With all the values known, you should start with the calculation. The first thing you need to find out is the absolute maximum damage you could do to an enemy with 0 magic defence. One example could be
code:
magic_damage := character_intelligence * 20
A character with 50 intelligence could do a maximum of 1000 damage.
However, consider this. What if you have a basic fire spell, and another fire spell, but you want it to be stronger? You may want to have the intelligence multiplied by a variable that is dependent on the spell being casted. For example:
code:
put "What spell would you like to cast?"
get cast_spell
if cast_spell = "Fire" then
spell_power = 10
elsif cast_spell = "Flame" then
spell_power = 50
end if
damage := intelligence * spell_power
With this code, the damage is 1000 for Fire, and 5000 for Flame. After setting max damage, you may also want to add a bonus spell damage based on level. Maybe you would like to have a % damage bonus based on level, such as a level 53 character have a 53% bonus to damage. The code for this is pretty simple:
code:
damage := damage * ( (level / 100) + 1)
After calculating maximum damage, you will need to set damage reduction for magic defence. Similar to attacking, the formula should be based on ratios between the magic attack power vs. magic defence, or something similar to this.
Most likely, there will not be an accuracy check for magic casting, because most RPGs do not have spell failure. However, if you want to add spell failure, the formula is similar to the accuracy check when attacking. See that section for the code.
The final result of the code is:
code:
put "What spell would you like to cast?"
get cast_spell
if cast_spell = "Fire" then
spell_power = 10
elsif cast_spell = "Flame" then
spell_power = 50
end if
put "What spell would you like to cast?"
get cast_spell
if cast_spell = "Fire" then
calculate_damage (10)
elsif cast_spell = "Flame" then
calculate_damage (50)
end if
This allows you to set the spell calculation into one set of code, and you can call upon it, with different spell_power values, depending on the spell that the player casts.
Resistances/Weaknesses/Immunities/Absorption
The formula for this is pretty simple. After damage calculations, you will use an if-statement to compare string values, and if a match is made, the spell damage is adjusted accordingly. For example:
code:
if monster_weakness = "Fire" then
damage := damage * 2
elsif monster_resistance = "Fire" then
damage := damage * 0.5
elsif monster_immunitiy = "Fire" then
damage := damage * 0
elsif monster_absorb = "Fire" then
damage := damage * -1
end if
As you can see, damage changes depending on the monster elemental attributes. If the monster is neutral to all elements, damage is not changed. What if you want to have multiple weaknesses/resistances/immunities/absorption? The answer is arrays. First, you will declare the variable as an array. For the next section, we will set up multiple weaknesses. Other elemental attributes must be added if you wish.
code:
var enemy_weakness : array 1 .. 8 of string
8 represents the number of elements in the game. The more elements you have, the higher the second number, because you need space if you want a monster that absorbs all elements, etc. After declaring the array, you would proceeed to the weakness setting. Let's make a monster have a weakness to Fire and Ice.
put "What spell would you like to cast?"
get cast_spell
if cast_spell = "Fire" then
calculate_damage (10)
elsif cast_spell = "Flame" then
calculate_damage (50)
elsif cast_spell = "Ice" then
calculate_damage (10)
elsif cast_spell = "Blizzard" then
calculate_damage (50)
end if
Now, the code that checks for elemental properties is slightly altered.
code:
procedure check_fire_elemental_properties
for i : 1 .. 8
elsif enemy_weakness (i) = "Fire" then
damage := damage * 2
elsif enemy_weakness (i) = "Fire" then
damage := damage * 0.5
elsif enemy_weakness (i) = "Fire" then
damage := damage * 0
elsif enemy_weakness (i) = "Fire" then
damage := damage * -1
end if
end for
end check_fire_elemental_properties
procedure check_ice_elemental_properties
for i : 1 .. 8
elsif enemy_weakness (i) = "Water" then
damage := damage * 2
elsif enemy_weakness (i) = "Water" then
damage := damage * 0.5
elsif enemy_weakness (i) = "Water" then
damage := damage * 0
elsif enemy_weakness (i) = "Water" then
damage := damage * -1
end if
end for
end check_ice_elemental_properties
The counted loop checks each of the various elemental properties. You can now call upon the procedures to check different elements, depending on the spell being casted. The final magic code would be:
code:
procedure check_fire_elemental_properties
for i : 1 .. 8
elsif enemy_weakness (i) = "Fire" then
damage := damage * 2
elsif enemy_weakness (i) = "Fire" then
damage := damage * 0.5
elsif enemy_weakness (i) = "Fire" then
damage := damage * 0
elsif enemy_weakness (i) = "Fire" then
damage := damage * -1
end if
end for
end check_fire_elemental_properties
procedure check_ice_elemental_properties
for i : 1 .. 8
elsif enemy_weakness (i) = "Water" then
damage := damage * 2
elsif enemy_weakness (i) = "Water" then
damage := damage * 0.5
elsif enemy_weakness (i) = "Water" then
damage := damage * 0
elsif enemy_weakness (i) = "Water" then
damage := damage * -1
end if
end for
end check_ice_elemental_properties
put "What spell would you like to cast?"
get cast_spell
if cast_spell = "Fire" then
calculate_damage (10)
check_fire_elemental_properties
elsif cast_spell = "Flame" then
calculate_damage (50)
check_fire_elemental_properties
elsif cast_spell = "Ice" then
calculate_damage (10)
check_ice_elemental_properties
elsif cast_spell = "Blizzard" then
calculate_damage (50)
check_ice_elemental_properties
end if
And that's it for elemental magic! For a more complex elemental formula, you may wish to have the user to have different % of elemental resistances/weaknesses/absorption. Immunity is automatically 0% damage, so that will not change. For example, you may want to set it so that if a player casts a spell that does 1000 damage, the enemy will absorb 50% of it instead, so instead of taking 1000, it heals 500! 300% weakness will make the monster take 3000 damage! And 75% resistance will cut the damage down to 250 damage.
Abnormal Status
Abnormal Status gives the battle a twist. It can do anything from making the battle just an obstacle, or can completely frustrate the player. If you have played a lot of RPGs, you will already know many of them. Some suggestions to use are:
Poison
Beserk
Confuse
Physical/Magical Damage Reduction
Rengeneration of HP/MP
Hit Rate Reduction/Improvement
Relection of Magic/Physical Attacks
Spell/Physical Damage Reduction/Improvement
Stats Increases/Penalties
Poison
This one is very simple. At the end of the round, you should add code that has the player take damage.
code:
if character_status = "Poison" then
damage := character_maxhp * 0.1
character_hp := character_hp - damage
end if
This has the player take 10% of Max HP damage per round.
Beserk
Beserk is also simple. At the stage where the user asks for the user's command, you skip it with an if-statement
code:
if character_status not= "Beserk" then
put "What would you like to do?"
get command
else
command := "Attack"
end if
And thereafter, you would have it select a random monster using random integers.
Confuse
This one is a lot more tricky. For simplicity reasons, I suggest that commands used in the Confuse status be restricted to attacking only. When you allow it to use magic, you will have to have Turing select a random spell, check if they have enough MP or not, and then have it select a random target. For the case of Physical attacks only, the result is similar to beserk. Instead of having a random integer for every monster in the field, you have a random integer for every monster in battle, plus 1 for yourself, because when you are confused, hitting yourself is a valid command. The coding is very similar to that of Beserk.
Physical/Magical Damage Reduction/Increases
Under the damage calculation, before HP is taken away, you use an if statement to check the character status, and adjust the damage accordingly.
Rengeneration of HP/MP
The code is very similar to that of Poison, only instead of losing HP, you gain it.
Hit Rate Reduction/Improvement
In the hit rate calculations, you may wish to add/subtract from the hit rate, to give a bonus or penalty to the hit rate.
Reflection of Magic/Physical Attacks
After dealing damage, but not adjusting HP, you would set the damage to 0, and have an equal amount of damage be dealt to the opposite target.
code:
if character_status = "Reflect" then
[damage calculation]
reflected_damage := damage
damage := 0
character_hp := character_hp - reflected_damage
else
[damage calculation]
end if
Spell/Physical Damage Reduction/Improvement
This is almost the exact same as the elemental attributes, with certain strings in status that adjusts the damage from spells or physical attacks.
Stats Increases/Penalties
For this to work, you must first have 2 variables for each stat. One for the base stat, another for the stat after bonuses. The stat after bonus should be altered when the status is in place, and when it wears out, you need to re-set it as the base stat, added by the bonusus from weapons, armor, etc.
Running Away
You should first have a condition from which an enemy can run away. First of all, bosses should automatically deny the chance to run. Otherwise, it should be based on the character's luck, agility, or any stats you wish. When you are sucessful at running away, treat it as a victory by setting all enemy hp values at 0, but replace the victory screen with some sort of running away message.
Other Notes on Battle System
Even though the battle system seems simple enough, there are many loops that you have to add if you wish to have a smooth-flowing battle system. You should give room for user errors by giving them a 'back' option, incase they issue a command, and wish to change their mind without wasting a turn. Learn to love the F2 button, as this will automatically indent the entire program for you, making it a lot easier for you to understand your own code. You don't necessarily need a flashy battle system; a simple format should suffice.
Items
Items are an important addition to your RPG. Although you don't need them, having them allows a more diverse game. Items have a variety of purposes, from healing, restoring status, dealing damage, advancing the plot, and others. However, even using a simple Potion to heal your HP can be more complex than you think. For example, I use this:
code:
procedure use_potion
if character_currenthp > character_maxhp - 100 then
put "You drink the Potion, and regain ", character_maxhp - character_currenthp, " HP!"
character_currenthp := character_maxhp
elsif character_currenthp <= character_maxhp - 100 then
put "You drink the Potion, and regain 30 HP!"
character_currenthp := character_currenthp + 100
end if
put "You now have ", character_currenthp, " HP."
put ""
put " Press any key to continue"
getKey
for decreasing i : 120 .. 1
if item (i) = "Potion" then
item (i) := "None"
exit
end if
end for
end use_potion
As you can see, this procedure combines if statements, with counted loops and arrays. Notice the first section of the if statement. You want to make sure that you do not exceed certain limits. For healing items, make sure you don't exceed maximum HP. For items that deal damage, make sure you do not exceed the damage limit, unless you want it to. An item system in a menu system is still being developed by me, so for now, stick with battle items.
Experience Chart
An experience system is the most common form of character development. After reaching a certain EXP amount, the character levels up, and recieves bonuses to stats, more HP/MP, etc. This section explains what the certain EXP amount should be. Obviously, a character should not level up every battle, nor should they level up every 1000 battles, because this is not fair to the player. The key is to give them a limit that's challenging, and rewarding when they level up. A good ideal EXP amount to level up should be 15-20 times the amount of the EXP that a monster with a similar level gives. For example, if a level 20 monster gives out 1000 EXP, the EXP to level up from level 20 to level 21 should be approximately 15000 - 20000. Of course, you can choose your own ratio, but this is a suggestion.
Other Experience Charts
Some RPGs may also have a separate EXP chart. The FF series have used MP (Magic Points, not the ones inside battle), and AP (Ability Points). Instead of using points, however, you may decide to make it's own EXP chart. Usually, these other EXP charts accompany a class system. They should reflect the abilities of the class itself, while the standard EXP chart reflects the mastery of the abilities to fight. For the next example, JEXP will be used as the other EXP Chart (Job EXP)Compare the relationship between EXP and JEXP to a game of chess. EXP is knowing the rules, and how to play. JEXP is developing techniques and strategies to defeat the opponent. Obviously, learning techniques and strategies takes a lot more time than simply learning the rules. Likewise, JEXP should be more difficult to obtain than normal EXP. Of course, you can have it the other way around, but this way make more sense. Finding the number of JEXP needed to next level up is similar to that of normal EXP.
Making Your RPG Better
Testing
VERY important. Testing is what makes your game works. There are 2 things to test for in a RPG:
Bugs
Balance Issues
Balance Issues are covered in the next section. For bugs, make sure that you enable the button bar at the top of the screen. Even if it get's in your way, enable it! With that, you can pause your program, and see if anything is not doing what it's supposed to do. Another suggestion is to open the debugger menu, and trace the operation of the program. With that, you can also see other bugs when running the program. Another thing to do is to comment out any delay commands, because although they help the reader, they do not help the programmer! All it does is make your testing phase much slower, so enable it when you decide to release it.
Balancing
While testing, you will most likely be coming across some balance issues. These are not bugs by definition, but still need to be fixed. While some attacks seem really powerful and nice, it is not fair to the player to have a skill to have a really good skill, without some sort of setback. Likewise, some skills may be very weak, even though they were not supposed to be. The solution to this is repetitive testing; you may also want other users to test for you, because this way, you can get more situations to test. Remember, if the user is not challenged, or the game is too hard, they will not like it as much.
Improving
So your game's perfect huh? Don't stop there! Add more! Make the battle system more complex, add a new dungeon, make more monsters, add graphics, anything that makes it more fun! Remember, until you can make a game of commercial quality, there's always room for improvement. So you've done all that Turing can do? Move your game to another language! Making a high-quality game all by yourself is very satisfying, so don't quit when you get stuck, or you think you're done, because if you are completely done, you'd be working at Squaresoft or something.
Final Notes
This guide was only designed for text-RPG coders and coders-to-be, since that's all I know how to do. Graphics RPGs will need this guide, and more, since not only do you have to get the computer to calculate all values properly, you now need to make it appleasing to the user's eye.
Remember, this is only a guide. Only YOU can make the decisions, and it's up to you to decide which of my suggestions you want to follow. For those who are coding an RPG, take my advice into account when coding it. If you are reading this, make sure that you can handle all the coding of an RPG before you start, because it would be very disappointing if you started, and then got stuck, and couldn't finish your final project. For all users out there, you've now seen the sheer amounts of code required to make an RPG, and I hope you can now appreciate the effort and time required to make one. Good Luck to those who decide to make one of the most simple types of games, and at the same time, is one of the hardest. Check for updates later on, when I add more.
Azndragon
Copyright 2002 Andrew Chung
And so, that's my tutorial. It's not that bad writing it, but just imagine adding all the formatting to it! Hope you guys enjoy it.
Sponsor Sponsor
Tony
Posted: Sun Mar 30, 2003 5:18 pm Post subject: (No subject)
wow... that is one big tutorial...
I'm gonna give you +20 bits now and more when I actually read it later on.
I've finally read your tutorial... wow... its long and VERY descriptive. I'm giving you a +80bits on top of that
Do you have nothing better to do then type a 9,000 word tutorial. Its good, but who is goining 2 read the whole thing.
-Nate
haujobb
Posted: Tue Apr 08, 2003 6:56 pm Post subject: (No subject)
I did
Asok
Posted: Wed Apr 09, 2003 12:04 am Post subject: (No subject)
I did ya lazy punk!
It's very good that azndragon decides to make the time to make a quality tutorial like this.
Besides, did it ever come to you that maybe he wanted to do the tutorial in the first place?
Eskimo
Posted: Wed Apr 09, 2003 10:36 am Post subject: Woah
That...is LONG! Beautiful too! This helps a lot, man, thanks
Vicous
Posted: Wed Apr 09, 2003 12:05 pm Post subject: (No subject)
wow, my brain hurts... this is long! but when you run away, you should not get as much experience and any items you may have gotten... consider an experience system based on how hard the fight was to win, no how strong the monster was... think about it
Vicous
Posted: Wed Apr 09, 2003 12:15 pm Post subject: (No subject)
and few if any spelling mistakes! gets my seal of aproval! lol
Sponsor Sponsor
FwuffyTheBunny
Posted: Thu Apr 10, 2003 12:26 pm Post subject: (No subject)
Great tutoral =)
Andy
Posted: Sat Jun 07, 2003 8:13 pm Post subject: (No subject)
you should make this into a book, burn turing onto a cd, and sell it as a bundle "Make your own REAL RPG"
krishon
Posted: Sun Jun 15, 2003 3:42 pm Post subject: (No subject)
ye, this is really nice, tho i did try to make an rpg earlier in the year b4 this wuz written. most of the stuff he put up there are essential in order to make it work. This is definitely one of the best tutorials on compsci. Good job
PHP God
Posted: Mon Jun 16, 2003 10:54 am Post subject: (No subject)
We should write a book. The turing manual sucks and doesn't explain things. Like in the first chapter it uses the randint function, but doesn't tell you what it does. It sucks so bad. Then agaian, a full turing manual would be really big.
krishon
Posted: Mon Jun 16, 2003 10:57 am Post subject: (No subject)
lol, ye, we can split up and write a section on a fucntion and then make it into a book
Andy
Posted: Tue Jun 17, 2003 10:24 am Post subject: (No subject)
ya then sell it to schools, so we dun have to use the crappy holt soft text book which is the exact same as the textfile -- lots of useless info 8)
Viper
Posted: Fri Nov 26, 2004 12:35 pm Post subject: (No subject)
ok im makin a rpg that is kinda like diablo and i wanna make a large map but i dont know how to make something larger than the screen and be able to see it(or move to it)