Step
1
2
3
4
5
6
6 b
7
8
9
10
11
12
12 a
13
14
15
16
17
18
19
20
21
22
22
23
24
25
26
27
28
28 a
29
29a
29b
29c
29d
30
31
32
33
34
34a
35
36
36 a
37
38
38a
38b
39
40
Directions
Attacking
Image
Lets start on our attack script. This will be used by you the player and monsters. We call all these the actors in your game. Lets think about what we have set up so far in our game.
We have:
Health
Level
Armor
Weapon
So the monsters should have the same stats so all actors in the game can use the same script
Attacking
We will use classic dungeons and dragons type of attack.
Determine surprise. The GM determines whether anyone involved in the combat encounter is surprised.
Establish positions: The GM decides where all the characters and Monsters are located. Given the adventurers’ marching order or their stated positions in the room or other location, the GM figures out where the adversaries are̶how far away and in what direction.
Roll initiative: Everyone involved in the combat encounter rolls initiative, determining the order of combatants’ turns.
Take turns. Each participant in the battle takes a turn in initiative order.
Begin the next round. When everyone involved in the combat has had a turn, the round ends. Repeat step 4 until the fighting stops.
In our game we do not have surprise, position or initiative. We simply walk into a monster to attack it. We may attack more than the monster or vice versa based upon speedy variable of the monster. The base speed of the character is 10. A monster will automatically attack you if you are less than 33 pixels from him.
reference
https://docs.yoyogames.com/source/dadiospice/001_advanced%20use/more%20about%20objects/parents.html
To Hit Script Flow Chart
Now that we have the variables we need lets create the script
The script will determine if we hit the monster
There are three possible outcomes:
Miss
Hit
Critical Hit
If you roll a natural 20 it is always a critical hit no matter what armor the monster has
If you roll a natural 1 it is always a miss
Create a script and call it toHit()
Before we create this complex script lets create a flowchart for it
Flow Charts are essential to break down what happens in a complex script.
Now Make your own Flow Chart we will do it in the simplest way here are your directions turn into the google class room when done
We will be using this info to create our flow charts and our scripts one script to determine if we hit the target the second to determine damage
You can modify your attack flow charts to make your script
reference
http://dnd4.wikia.com/wiki/Attack_roll
Damage Flow Chart
Can you create the damage script on your own?
Think of this script as an input output machine.
You put in a value and it spits out another value.
Scripts can also be used by any object in your game
Create Code for To Hit script
The good thing about using scripts is you can modify them at anytime without changing other code
In the script we are passing 2 arguments. What this means is that 2 numbers will be used by the script to return damage
Remember to add the /// comment this will also auto-fill the arguments needed when you call the script
We need to assign a new variable in the monster object and call it result so go to create event of the monster add result=""; and also add level = 1;
Now create the script called toHit this script will determine if the attack is a hit and what type of hit normal or critical.
The variable result will hold the result of the roll as a string value.
This string value will be used to update the Event Log
Can you follow the code by looking at the flow chart?
Create Damage Roll Script
Now we will create the damage roll script
This will use the result of the AttackRoll script to determine the damage dealt
Notice that the result that we got from previous script determine how much damage we deal
dam*=2 code is how we multiply the dam variable by 2
Add Roll Dice script
Since our monster has hit dice to hit lets create a script to roll the dice and give a number for damage
You can find this script at GMLscripts.com
Call Scripts
Now we need to "call" the scripts or run them at the correct time in the game open the monMove script
Can you find where an attack should take place i this script?
Yes when a monster is less than 33 pixels from the player and attack occurs since this will also only happen once per turn.
We need to add a new variable result=""; to the create event of your player
Also notice how we call scripts with arguments
result = toHit(level,global.armor);
level is the level of the monster
global.level is the level of the player
global.armor is the armor of the player
damage is subtracted by the players hit points
global.hp-=damage;
We also add the result of the attack to the text log with:
ds_list_add(global.text, "The "+string(name)+" "+string(result)+" you.");
Use Attack Scripts in Player
Now we will use the same script to get the result and damage when the player attacks a monster.
Open the playerMove script
When should an attack take place in this script?
We need to think about this a bit what if you are surrounded by enemies?
You can only attack one monster per turn so how do we target a particular monster?
We will have to press a key to toward the monster we want to attack
So we will have to check if there is a monster in the direction we press to start the toHit script.
If you look at the playerMove script you will notice that we check if anything solid is in the way of our character before we move in that direction. Since our monsters are flagged as solid we cant walk over the top of a monster.
So we need to make a second check after this one that looks for a monster in that direction
We also need to check to see if a monster instance exsists to avoid and error in the game ( We cant check for an instance that doesnt exsist)
This script call is codey if that is a word and can be optimized for those with the skill.
Can you think of a way to optimize this script call.
A few new things are in the call. One is getting the ID of the monster.
Every time you put and object in your room it is given an instance ID. Each one is unique and it is how game maker identifies it in the game. So if you have 5 skeletons in your room each has a different ID.
This will need to be added for all 8 directions However you could change all the code inside the instance exists and place_freecheck into a script to keep it cleaner
Add Death check to Scripts
When we test the attacking script we notice that an attack takes place damage is dealt and the text logs gives us info
The monsters and you never die when the hit points reach 0 so lets add a new check for death.
What we have to do is add a new instance variable that will be able to be changed if you kill the monster so line 22 will get the value of the name of the monster you are attacking and place it in name variable
The reason we have to do this is because we destroy the monster if its hp falls below 0
We also use the with construction to destroy the monster whos ID we have targeted previously
Add Experience to Kills
Every-time you kill an enemy you should gain some experience.
You can make the level, hit points and exp static or random like I have done
irandom_range is a function which will choose an integer between the two #'s you select
This seeds all the other variables hp = level * 6
XP = level * hp
You could just put in numbers like:
level = 3
hp = 20
monExp = 30
I like to make it more random.
You need to experiment with the monster variables to make your game balanced not to easy and not too hard.
Create XP Script
Lets create an XP to the script that will check to see if you level up after each kill
We will use a XP formula that is non linear that is it takes more XP to level as you get to higher levels
Add Level Check to playerMove script
Lets add the level check now
If monsters HP is less than 0 we run the level check script after we add the monsters exp to our global.experience variable
Here is a table of experience need to level.
How much experience is needed to get to level 10
Add Hit Points to Character if you Level Up
If you level up you should gain HP, attack and armor.
So lets add to the scr_expericene script and use a dice roll script to randomize it
We will find this script here http://www.gmlscripts.com/
This site has lots of scripts for you to use.
By seeing how others code it will help you code
Optimize the script
The playerMove script is getting big and hard to follow so lets see if we can optimize it by creating a script that will run the code
What is the only thing that is different on attacking from the 8 different directions?
The only thing different is the x,y coords we check so lets pass these coordinates to the script and run it to make our code look cleaner
Go to the Create Event of your player and add two new variables xoff and yoff these are the offsets that we will change for each direction then create a script that will move if place is free and another script for attacking the monster this will clean up the script by adding sub scripts
The scripts moveIfPlaceFree() and attMonster() are the same code as in the original except you replace the x+32 with x+xoff and the y+32 with y+yoff
Old playerMove
New playerMove
MoveIfPlaceFree script
Lets create a script that replaces the code that allows the player to move if no obstacle is in the way
Create a new script call it moveIfPlaceFree
attMonster Script
Add a new script and call it attMonster
This will replace the attacking script in playerMove
Notice I moved the energy added to obj_monster before we destroy the monster
This will stop any error from occurring when you kill the last monster in the room.
Can you predict why an error would occur if we add the energy after we destroy the monster?
Add new scripts to playerMove script
All we have to do is add the correct xoff and yoff to each direction then add the two new scripts
Make player die if HP is exhausted
Now we need to make the player die if hp runs out. Since this is a rogueLike game the game is over if the player dies
So we will make a room called the death room that displays the headstone for your player with his ending stats. You could also have high scores listed, experience, I found a gravestone sprite and added some text.
To customize player name add a global.playername = "your Name" to the obj_variables object
We also want to be able to quit the game or start a new game
So we create an object called obj_death and place it in the roomDeath
Add a step event with keyboard checks for Y and No
Add Draw Event
Add HP Check to Player
Now we need to check if the player has died we will do this whenever the player is attacked by a monster
Go to the monMove script and add the HP check
This will go to the death room the instant your character dies
You could start an alarm to make this trip delayed
Loot Drops
When you kill a monster it should drop some random loot
We already have the pick up loot in place however we want a monster to randomly drop loot based on a chance
Then if an items drops we want the item to be randomly created with more valuable items dropping the least.
We also want more valuable items to drop more frequently the higher your level is.
This is a lot so lets take them one at a time
First lets make your monster drop loot object
We need to create a script called chance that will check if we drop an item
This script will take the level of the monster to determine drop rate
So a level 1 monster has a 10% chance to drop something
level 2 20% chance
Level 10+ 100% chance to drop loot
This script will return true or false
Loot Drop Rate
This script requires us to organize our loot object so that each item is arranged from easiest to drop to hardest
And you need to figure out what chance for each to drop
Go to the create event of your obj_variables and add comments describing the drop rate of each we also need to add the drop rate for each item so we will change this to a 2D array like shown
So now we have loot[0,0] the first number indexes the item
the second number stores the name in position 0 and drop rate in position 1
the third position[0,2] stores how many you have collected
We also have turned these into global variables by declaring them with globalvar by doing it in this way we dont have to add the global. in front of it which is annoying
So gold will drop the most frequently diamond the least
scr_lootDrop
Now lets write the script we pass the level of the monster to this script then convert it to decimal
Then we run the chance script to see if the monster drops anything with the chance increasing by the monsters level
If the monster drops something then we determine what item is dropped again based on chance plus level
Line 13 creates a loot object
Line 16 rolls a random number between 0-100
Line 17 adds the percent of your level to this roll so the chance of rare item increases by 10% for each level
Line 15 - 27 determines the loot drop based upon the chance in the 2D array
with inst sets the variable type to the drop so when the instance is created it has the correct sprite
Monster Destroyed
When a monster is destroyed we want to run the loot drop script
Open the obj_monster object add a destroy event and add the script call
Add Drop to Event Log
Now that our game log is in place it it easy to add text to it
Open the scr_lootDrop script
Right after we determine what drop it is place the ds_list_add code to add the next line to the game log
Join YoYoGames forum
Join the forum and post a question about your game
Getting advise from other programmers is a great way to get help when you get stuck
You can post an error you are getting?
You can post a "How do I?" question
You can also search the forum for ideas or more efficient ways to code your game
Go to https://forum.yoyogames.com/index.php
Create account and log in I usually put my questions in the programming sections
Join Game Maker Forum and post a question
Now we want to join the yoyogames forum and post a question about your game code
Make sure you follow your post so you will be notified when a new answer is posted
A simplified example in action: Monster is killed! What does the game do to determine your reward?
Weapon Sprite
calculates the number of items to drop
selects item types
selects item qualities
selects certain unique or set items if needed
selects item properties
This would be ideal for the drops in your game.
Since we want our character to use weapons and wear armor
Weapon Variables
Lets set up some variables to use for the weapon choices
The weapons need to have the following:
//Type of equipment 0=Weapon | 1=Helmet | 2=Boots | 3=Armor
//sprite
//Item sprite index
// Name of weapon
//Attack & damage rolls
//Attack & damage dice
//Bonus 1 Type | 0=HP | 1=Armor | 2=Attack | 3=Damage | 4=Critical
//Bonus 1 Amount
//Armor Increase
//Sell amount
//Equipped or not
We will set up a 2D array to keep track of these things
We will set up a single sprite with subimages for all the weapons
I have 5 different weapons in my game the sprite is in order from lowest damage weapon to highest
Our goal is to create a system that can work no matter how many items we add to the game it will still work
It is very important that you order your weapons from weakest to strongest in the sprite
By setting up things in a systematic way to start with you can use these variables to determine drop rates
notice we also set up two globalvar these are global variables that we dont have to add the global. in front of it because we set it up with globalvar
ITEMVALUES is used to keep track of how many properties each array variable has 12 in our case
We also need to create our ds_list to keep track of all our inventory items
and we will create our ds_grid to keep track of our equipped items
The weapons must keep track of rolls and damage per roll and name
The armors must keep track of name and armor increase for each type
Global Variables in obj_variables
Weapon Object
Now we will create our weapon object so that we can collect items
Create an object and call it obj_weapons give it the weapon sprite you have created
Add a Create Event and for now lets just randomly pick one of the objects using irandom_range
Add a Collision Event with your character so you can pick up the object
and add it to your ds_list
When the player collides with the object it will store all of the information in the ds_list
This will allow us to create a unique weapons on each drop by running drop scripts later for now it will just create a different weapon with no special attributes
The Draw Event will draw the sprite with the corresponding sub-image
It will also draw a glow if equipment is magical
So create a sprite called spr_magicGlow 32 x 32
Create Event obj_weapons
All your other equipment will be a child of your weapon object only the Create Events will be different for each
ds_lists are lists of numbers that are added from left to right with ds_list_add
Can you Map a ds_list?
Lets map one together to understand them better
Your other objects have to use the appropriate variable to assign its name in equipment[3] position
Only your weapons have attack and damage rolls so the rest of your equipment will have 0 for the value of equipment[4] and equipment[5]
Collision with Player Event
Draw Event
Create Inventory Page
Now that we can pick up items we want to be able to look at what we have collected and see the properties of each item
Create a new object and call it obj_inventory and variables to the create event
inventory = false this will keep track of if the inventory panel is turned on or off
equipmentSelected = 0 this will keep track of what item we have selected in the inventory
We also need to create a selection sprite to show which item we currently have selected
I mad mine 30x30 and made it a blue outlined rectangle
Create Event
Step Event
We want the inventory to pop up when we press the "I" key and game play to be paused
So in the Step Event of obj_inventory we will check if the "I" key has been pressed
If we press "I" it will toggle the variable inventory from true to false and vice versa
using inventory=!inventory
If inventory is true we do the following:
get the size of the ds_list
deactivate your player to pause the game
check if we are pressing up or down to scroll through the items in your inventory
Remember if anytime we use a new global variable set it in the obj_variable Create Event
so global.enchant is new so set it to global.enchant=false
Create Inventory Object
We want the create the inventory object from your obj_gui
So add a new step event code this will pause the game by deactivating your player
It will also create the obj_inventory
Inventory Page Draw Event
In the Draw GUI Begin Event create a new code
obj_gui Step Event
By creating a new code exe for each draw action it keeps the code compartmentalized and easier to find errors
Remember to add /// as the first line this comment will give each code a name that will show up in the action properties call this one Draw Inventory items
This code will draw the items in you ds_list by looping through the list
Each loop it will get the values of each position in the list using ds_find_value
Look through the draw code if any of the scripts are white that means you have not created it yet so remark it out by placing // in from of the code
//getBonusType is one script that has yet to be written line 29
also since the getBonusType script is not written we dont know what the value of bonus is yet so remark out the
//draw_text(500,100+(i*25),string(bonus)) on line 38
unEquip Script
Now we need to create our un-equip script so we can take off equipment and put the other piece back in your inventory
We send what type of equipment we are taking off and the script does the rest
getBonus Script
Now lets create out getBonus script
When this script runs it will first check your weapon for any bonuses
It will use a switch statement and check what type of bonus that your weapon might have
If it does have a bonus it will add it to the variable
Next it checks all armor for bonus armor and add all those up
These variables will be added to the draw stats code in the draw event of your gui
It will also be added to your attack scripts
getBonusType Script
This script will be used to get what type of bonus your enchanted equipment has
getBonusAmount Script
This script will be used when you enchant equipment
Draw Player Avatar for equipped Items
Now we will create a panel that will show what items you currently have equipped
Create a sprite that is same height as your GUI sprite so 128 px in height and 128 px wide
It will look like a tic tac toe grid
part 2
Draw GUI Event
In the middle cell we will draw the player sprite
Top cell helmet
Right cell weapon
Left cell armor
Bottom cell boots
You can use the other for cells for other items you may want to have your player wear latter
This will be draw on the GUI
Make a new Code in the Draw GUI Event of obj_gui call it
we will do the following:
Draw the new tic tac toe sprite
Draw your character Sprite
The variable xoff and yoff are used to draw the equipment sprites offset by a set amount of pixels
You may have adjust these offsets to make the sprites be drawn in the center of the grid
Next we check if you have an item equipped with ds_grid_value_exsists
If a value is stored in the grid we will draw the correct sprite in the correct spot
Challenge can you do these for events in a better way?
Could you use a for loop to draw them and make your game for efficient
Also notice that we coded the drawing of object that we dont have made yet.
However you will see that making more items is very quick once we get the weapon working
Add Weapon attributes to Characters
Now we want the equipment you wear to add their bonus to your characters armor, HP etc.
To do this we will check the ds_grid for any items you have equipped and add any bonus
Your grid contains your equipped items think of the grid as slots that contain all the information about
each piece of gear you are wearing
ds_grid Example:
We will need to check for the add all these bonuses to your characters base HP, Attack and Armor
So we need to set up some global variables which will hold the values of the bonus attributes
Open the obj_variables and add these new variables
Go to the obj_gui and add this to the Draw Stats code in the Draw GUI event
Create your Equipment Grid
We have learned about ds_list 's now we will learn about ds_grid 's
The difference between a list and a grid is a list is one list of data separated by commas
A grid is organized in rows and columns
Use this template make a copy of your own and add your weapons to the grid it will make it easier to understand where the data is stored
https://docs.google.com/spreadsheets/d/1l965lmySx8zE5rEvEy_C4KD9a3iUmoSlKTcukyBl9Kk/edit?usp=sharing
Obj_variables
Draw GUI Stats
getBonus script
Add Critical Bonus to Attack Script
Now we have to make these bonuses apply to our battles with monsters
Open the AttackRoll script and add the bonusCritical when it checks for a critical hit
Add Damage Bonus to damageRoll Script
Open your DamageRoll script and modify it to give you the bonus damage
Also call the script in the attMonster script
Challenge
Lets see if you can add a special effect if you get a critical hit
The code to create a special effect is
effect_create_above(ef_explosion, x+8, y+8, 0, c_red);
Try to figure out where to add this code for a nice effect on critical hits
Any problems with attack scripts?
Now that we have added bonus to the AttackRoll and DamageRoll scripts you may notice something odd
The monsters are hitting much harder that is becuase the monsters are taking advantage of your bonuses
So what can we do?
We can simply make copy of each script and customize it for the monsters so that it doesnt have the bonuses
We must also change the script name from the calling position so that the new scripts are ran when the monsters attack
Copy the toHit() script and rename MontoHit()
damageRoll Script
attMonster Script
attMonster script
monMove Script
Copy the damageRoll() script and rename MondamageRoll()
Now remove the new code from the monster scripts to make it just like it was before
Now go to the monMove() script and change the script call to point to the new script
MontoHit Script
MondamageRoll Script
Adding More Equipment
Now that we have a really cool game its time to add more equipment
Since we set up our weapon object the way we did it will be easy to add as many new types of equipment as we want
We are going to add a helmet, boots and armor
You can add more once you figure out how easy it is to add more equipment
First lets Create two scripts
One script will randomly drop a equipment based on your level
So at level 1 it can only drop a club or dagger once you reach level 10 you have a chance to get a sword but very low
The second script determines the quality of a weapon which is the plus variable
ref:
https://docs.yoyogames.com/source/dadiospice/001_advanced%20use/more%20about%20objects/parents.html
scr_equipDropKind
scr_equipPlusCheck
Change Weapon Objects Create Event to run scripts
This will make the drop rate random and weighted so at low levels only weak equipment will drop as you increase in levels you chance for a great weapon increases
Set Up Helmet variables
Open you variables object and you will add new variables for your 5 types of boots
Helmets only need a name and armor since they dont increase your attack or damage
Now make a obj_helmet and make its parent the obj_weapon
Make the helmets progressively better
Example:
helmet 0 has 1 armor
helmet 1 has 2 armor
helmet 2 has 3 armor
helmet 3 has 5 armor
helmet 4 has 7 armor
Put a few obj_helm and your room and make sure everything works just like the weapon
You should be able to:
pick up helm
helm added to inventory
helm can be equipped
helm image will show up on gui when equipped
armor is added to your character
If all this works make your obj_boots then your obj_armor objects using same procedure
You could even add rings, shields, alternate weapon etc
obj_variables
Create Event of obj_helmet
What would you need to add another piece of equipment?
Create sprite and object for new item make it parent of obj_weapon
Change Create Event of obj_shield to get the correct type range 25-29 in my case
Add another type to the variables list and create variables for new item
equipment[i,0]=4 //Type of equipment 0=Weapon | 1=Helmet | 2=Boots | 3=Armor | 4 = Shield
Make Sure your ds_grid is big enough to hold 5 items
globalvar epuipmentGrid;
equipmentGrid = ds_grid_create(11, 5); // This will create a grid for your equipment
Draw Sprite on avatar when equipped
//Get Sprite of shield postition 7
if ds_grid_value_exists(equipmentGrid, 0, 4, 0, 4, 4)
{
var shieldSprite = ds_grid_get(equipmentGrid, 1, 4)
var shieldSpritesub = ds_grid_get(equipmentGrid, 2, 4)
draw_sprite(shieldSprite,shieldSpritesub,248-xoff,688-yoff)
}
Add shield to getBonus() Script
Change size=4 to automatically get the size of the grid using ds_grid_height
Thats it so easy try it
Other Equipment
These are the create events of the other pieces of equipment
Add Bonus to attack scripts
Now that we can equip items we want those bonus to be part of the battles
Draw Collected Gems
Lets draw the gems and gold we have collected on the gui
Gems will be used later to enchant equipment and make it better
Make a new execute code in the Draw GUI event of you obj_gui
Boots
Armor
Shield
Ranged
toHit script
The Gold will be draw from the Draw_stats code
We will get the value stored in the lootGrid and draw it on the GUI
Whats Next
In the third section we will make the monsters drop equipment or loot
Give the equipment a chance to have bonuses
Make the bonuses increase as your level increases
Make a NPC that can enchant your equipment to give it more powerful bonuses
Automatic monster spawning
Boss Room design
Play the Rogue Like Game
http://munificent.github.io/hauberk/
Need a script find them here
Lots of code sprites and ideas from HeartBeast