5. Consumables & Item classes
a.) Introduction to consumables like postions, bandages and similar
b.) Items may be of different quality and or for different character classes like Warriors don't wear Robes and Mages can't hold a sword.
Article 5
5.a. Consumables
In the first part of this article we cover consumables. Consumables are items like potions, for example. We want to keep it simple that's why we only cover three potions in this article. We want to have one for health, mana and one for both values. Once you know how to flag items in the database as consumables there are no limitations on what you want to add. You could add scrolls, bandages, tomes for spells and even potions with time limitation that will buff a attribute of your character for a certain amount of time.
What we do for the programming side is that we add a new column to our item database named "consumable". When this is set to "1" we use it as a reference in our inventory. When we now right click the potion in the inventory we add the bonus values to our current values and destroy the item from the inventory. For this to work we need to modify our character. We need to seperate hitpoints and manapoints into "Current Hitpoints" value and "Maximum Hitpoints" value, same for mana. Our potions only restore the current health/mana value.
For example:
Let's say our character has a maximum of 100 hitpoints. After a fight with an enemy he now has a current hitpoints value of 80.
80/100
Which means he lost 20 hitpoints. Our heal potion regains 50 hitpoints. This would result in 130/100. Now the current hitpoints value is way bigger then the maximum value therefore we add a simple value comparison and correct the value:
CurrentHP > MaxHP --> CurrentHP = MaxHP
We do this for mana too.
In our Event Editor our events look like this:
1. We check for a click with the right mouse button onto the "ap_Item"
2. We check if that "ap_Item" object has a consumable value (new alt value!) greater then 0.
3. Now we seperate events for mana and hitpoints:
a.) Is our bHP of "ap_Item" > 0 , so we check if that item will grant us extra HP
b.) Is our bMP of "ap_Item" > 0 , same for mana
4. Now we da a comparison of
This means in short: is current HP + bHP from potion ">" our Maximum HP (STA*10+bonusSTA*10+bonusHP)
If that is true we simply write our maximum HP value into our current HP value.
e.g. CurHP 70, MaxHP 90, potion will grant 50 bHP so 70+50 = 120
120 > 90 = Current HP will be set to 90.
If the above statement is not true then we read our current HP value from the array and add the bonus HP from the potion.
This looks complicated, you better check it out in the event editor for yourself later.
The cool thing is that the code for mana and hitpoints is seperated. We don't need to code anything for our rejuvenation potion. MMF will execute the code line by line so our rejuvenation potion has a HP AND MP bonus. So both events will trigger:
Let's say we have 10/90 HP and 90/90 MP.
The HP event code will be triggered to add 50 HP while for the MP the event code will simply replace current mp with max mp, therefore 90 stays 90.
Thats pretty much it!
What we do not cover for the coding but you may like to add for yourself is consumable stacking and temporary buffs. Read on and I will explain how this will work in our current application:
For stacking we need to make sure that each set of potions follow each other ItemIDs by 1, like:
ID 13 - HP potion
ID 14 - 2 HP potions
ID 15 - 3 HP potions
... and so on
Modify the consumable value to the amount of potions, like:
ID 13 - 1 HP potion - value 1
ID 14 - 2 HP potions - value 2
ID 15 - 3 HP potions - value 3
... and so on
What we do now for the coding is when we use the item on rightclick, we replace it with the "ItemID" one step below our current "ItemID":
First we check the consumable value. If that value is bigger then 1 it means that we have at least two items stacked. In our example above it would mean our current "ItemID" will be 14 (2 HP potions). When we now right click this item we want to replace it with "ItemID" - 1 which will be 13. 13 has now a consumable value of 1 which means when we use it, it will be gone from the inventory as it represents only one potion left.
That is the whole trick for "useing" stacked items.
Now for "combining" items we need to do the following:
Let's say we can stack at a maximum of 5 items:
"ItemID" 10-15 are now our HP potions with consumable values 1-5.
Let's say the player picks up a stack of 5 potions and clicks on a stack of 2 potions.
We add both consumable values (5 + 2) resulting in 7 which is bigger then 5 so we execute the code for swapping! This would be the same for every combination bigger then 5.
If the player picks up a stack of 3 and clicks on a stack of 2 potions we add again (2 + 3) resulting in 5 which is smaller ( and or equal) then 5 so we will replace the item with "ItemID" of the inventory item + "Consumable" value from the picked up item.
"ItemID" would be 12 for our item in the inventory. The item we picked up has "ItemID" = 13 and "Consumable" value 3. "ItemID" 12 + consumable value 3 equals in "ItemID" = 15! We then delete the item from our cursor and change the one in the inventory to 15. Items are now stacked
What you also could do is that you make stacking always possible. Let's say you want to combine 3 and 4 potions. With the coding above you will swap them as they both added together are bigger then 5. What you could do is, that you change the one in the inventory to 5 and the picked up one to 2.
Cursor: 3
Inventory Slot: 4
5(our max stack)-4(inventory slot) = 1
new Inventory: 4+1 = 5
new Cursor: 3-1 = 2
Simple math.
Obviously this is the more professional solution
Diablo I does not use item stacking but Sacred I and II for example do.
As for temporary buffs we would include a new value into our character value combination. Right now we add base attributes, bonus attributes and bonus ratings.
This could be a new Z layer in our "char.db" which could look like this:
BonusName, BonusValue, Time
bSTR, +1, 8
bSTA, -1, 10
"BonusName" is the name of our attribute or rating, like "bSTR","bHP" etc.
"BonusValue" is the value we want the attribute or rating to be modified.
"Time" could be a reference to our game engine time. This could mean frames, turns, minutes or hours. Whatever you prefer.
In our example we want it to be turns.
So this would mean we get a +1 "STR" buff for 8 turns but we also have a "STA" debuff of -1 for 10 turns.
We call this a state. A state is a blessing (Buff) or a curse (Debuff) which influence our character values. Our character could be poisoned loosing hitpoints every turn for a number of turns. He could also be blessed by a priest to get a "STR" bonus for X amount of turns. This is totally up to you what you want to design.
To finalize it, when reading our base and bonus attribute we also include the value from this array.
For hitpoints for example:
"baseSTA" + "bonusSTA" + "bonusHP" + "tempbonusSTA" = final "STA/HP" , then presented to the player
So far so good, time for a quick example download, check it out below:
Item classes is a advanced feature only real Action RGPs really need. This heavily depends on the amount of characters you can choose to start your adventure with. I will not cover any real coding and I will NOT include this into our current example.
You may remember when we talked about item databases and how a professional item database could look like. This would be something you want in a professional database instead of our simple one. Also usually small RPGs only feature one character and may allow character customisation based on attributes only.
So a Knight may start with more strenght and stamina then a Mage who relies on intelligence.
So item classes are more a characteristic for the item.
Let's take weapons in general, each character can wear a weapon. But you may want to limit certain types of weapons to certain characters. For example:
Again, there are two ways to achieve this from the coding side.
1. You setup a row for each character in our current item database and change the value to "1" if the character can use the item.
In our current solution it could be like this:
..., "Mage", "Knight", "Hunter"
..., 1, 0, 0
That would limit the item to be Mage only.
The events to equip items would also need to be modified to compare the current character class to those fields and then either allow the item get equipped or not. Also the tooltip needs to be modified.
This would work ok in our current solution.
2. For a professional solution you would add only one row, our "ItemClass" row. Now each type of item would have it's own ID. You would make a new Z layer for our new "ItemClass" database:
1 would mean the Knight and the Hunter class could use the item.
2 would mean only the Knight could use the item.
And so on ...
Now you can just ID all your items. Again this is important for balancing. If you have 1000 Swords and decide you want to add a new class you only add a new row to the item class database like "Necromancer" or "Rogue" and set the values and the character will be able to use all those items. Also if you decide that Mages should wear Shields you can simply change the value in the database and all Shield items will now work for the Mage.
If you want to be more specific you could add a fifth row and call it "ItemType" and reference it to a value in the item database. So let's say a helmet is 1, sword 5, poleaxe 10 and so on. Again the limitation is your imagination!
That's it! Stay tuned for the next part when we cover durability, sockets, inventory sorting and lootlists!
Comments are welcome as always, PM me if you have questions.
This will be the end of the fifth article. I hope you had the same fun recreating stuff like I did writing this for you! Again comments are welcome.
Are you going to explain how to add an item to an empty space slot when i click "Add Item" buttom?
This tutorial is great, i've made a diablo style inventory once, but this one is so much better ^^