Programming a Role Playing Game?

BlitzMax Forums/BlitzMax Programming/Programming a Role Playing Game?

zoqfotpik(Posted 2012) [#1]
I'm interested in programming an RTS game with strong RPG elements.

How would one program an inventory system in Blitzmax? I want stores, enemies and player characters to all have inventories. To complicate matters, I want the weapons to be procedurally generated-- either generated in a worldbuilding step a la Dwarf Fortress or generated on drops.

Any suggestions? Should I have a template class Item, and have all inventory items extend Item, and have an Inventory class which has a list that can hold type Item?

Anything else people have run into?


SpectreNectar(Posted 2012) [#2]
I wouldn't recommend that you use an item type. That would work for 5 or 10 items, and then it'd be unmanageable from then on. Rather, I'd make a mechanism for reading my items from some kind of external file(s). If you want you can always encrypt your file(s).
Then I'd either make a small item editor or edit the item files manually.

You have to consider what properties your items should have. Price? Weight? Name? Attack modifier? etc.
DO you want for instance keys to unlock certain doors? Are there any other non general items such as an item that changes the flow of the game in any way? Make a function and maybe teach the files to call it.

So my main focus would be more on how do I get the items to be able to do what they should. Now the question of making an inventory itself boils down to storing a list of these items and probably drawing them too.


zoqfotpik(Posted 2012) [#3]
So you might have a flag for "is_weapon" that would allow it to be equippable in a weapon slot?

I see what you're saying about this.

What if the item had been unique and generated on the fly? You would then just have the character's inventory write out all weapons it contained when the character was saved? That seems like a good way of doing it-- the parameters are contained in the weapon itself and on creation they are produced as copies from some sort of template.

Any other thoughts on this?

What if I wish the weapons to have different types of ammunition? Should the ammo be likewise defined as a string, eg. a "weapon" class inherits from "item" and contains a list of add-ons and a "magazine" object which in turn contains bullets?


SpectreNectar(Posted 2012) [#4]
Sounds reasonable. And you're right, saving items generated on the fly goes well together with the idea of items being files in the first place.

About ammunition I think it should be a separate thing. There's more than one way to go about this, depending on if this has to be randomly generated too, or if there's some predefined types of ammunition. In any case it's a more narrow concept. What I mean by that is that bullets have less properties, and those that it has are similar. What is the speed and position of the bullet? What color or image is used to draw it and how much damage does it deal.
You can be ambitious though. Have elemental or poisonous damage etc. Have a flame thrower or a beam kind of bullet. These are all considerations to make.


Other thoughts? Well, depends on how you want to do it :)
How the weapons work in particular. What kind of items there is to exist other than weapons.


angros47(Posted 2012) [#5]
@zoqfotpik

Will your game be related to Star Control? (I noticed your nick)


Banshee(Posted 2012) [#6]
Well not having yet put a great deal of thought into it as I'm not solving this problem myself atm, but I would probably have a general item model class that is the same for all inventory items. I wouldn't extend off it, I would have separate control class which effect the properties of the item.

To me the item type would literally just be a container for data. A property of "meshType" would indicate what mesh is used when rendering, but the process of loading and displaying that mesh would be handled by a completely separate subsystem.

I like to separate out my data type from my control classes, and i'm experimenting with various methods of then separating out the display logic too. As this way data is just data, control classes can be run on threads, and display classes just interpret the resultant data in the model.

So a data model class which just holds the properties of your generated weapon, helmet, potion or whatever else is all that would be needed. The "weapon control class" would likely be instantiated by making an attack, and it would then just look at whatever data has been loaded in to the characters inventory space for the weapon to calculate the attack and negotiate with the server if in multiplayer.

Ammunition prusumeably goes in an ammo inventory slot - so this is handled in exactly the same way, and its properties are stored in the same class that all other items are stored in.


PowerPC603(Posted 2012) [#7]
I'm also trying to design such a system for my game.

I was thinking about using one base type (TItem), from where everything else in the game is extended.
A weapon is extended from this TItem, as well as armor pieces, potions, normal loot, quest items, skills.
Even buildings, trees, rocks, monsters and NPC's could be extended from this TItem, but I'm not sure about this yet.

This way I think it's easier to put stuff in your shortcut bar (usually located on the bottom of the screen), as each slot only needs to accept TItem.
Also to put everything in your inventory is easier, as everything can fit in there.

Using items and processing them can be done through methods (accessing extended fields directly from the inventory isn't possible, as the inventory uses TItem types which don't have access to the extended data).
Then you can program the behaviour of every item-type (potion, weapon, armor-piece, loot, shield, ...) specifically for each extended type.
This would also mean searching and fixing bugs would be easier, as everything a weapon does, is contained in the TWeapon type.



Using only one type would mean you have all your code mixed up with everything else, and bug-fixing would require you to search through ALL your code.



If you would use only one type, from which there are no extended types, you would need alot of fields in that type to hold everything an item could possibly ever need.
If you have only a few items, it wouldn't matter, but if you plan to create thousands of items, that would mean you allocate alot of memory because of all the fields each item has, and you won't ever use half of those at the same time for any item.
It's a big waste of memory.

The TItem type would have these fields: Attack, Defense, Evasion, Accuracy, HP, MP, Delay, Level, Experience, ...
A HP potion for instance wouldn't have any use for Attack, Defense, Evasion, Accuracy, MP, Level and Experience. Only the HP and possibly Delay fields would be used by a HP potion.
All the rest isn't used, but it will be allocated by your code because all those fields are bound to the TItem class.

If all these values are Int's, it means an HP potion uses only 8 bytes of data, but you allocate 36 bytes of memory for it, where every unused value is 0.
If you have 1000 potions, it's a waste of 36kB of memory.
I know memory isn't a big issue these days, and heavy optimization to kill every unused byte is a waste of time, but still, I think it's bad practice to allocate 36 bytes for an item while only 8 bytes will be used.
And these are only basic data, you'll find alot more values later on which also add to the wasted memory.

You would also need alot of methods which all have a big Selefct-Case structure to define what you want to do, based on the type of item.
If you execute the Equip/Use-function of your item (like Weapons, Armor, Shields, Potions and other consumables), you will want to Equip Weapons, armors and shields, while you want to Use potions and other consumables.
Even other types of item don't have such function, like normal loot that's only meant to be sold. These don't usually allow to be used or equipped.
Your code would need to detect this and execute a separate piece of code based on the kind of item.

Using methods ("Method EquipUse()" for example) in extended types means your base type has all methods without code in them.
So every extended type could have such a method as well, all with their specific code.
If you would execute the Equip/Use function this way, your weapon, armor and shields types have code for this (applying the 3D model of the weapon to your character and moving it from the inventory to the weapon-slot).
The potion would be consumed and applied (increasing your HP for example).

Every other extended type doesn't have these methods (like normal loot), so the base-class EquipUse() methid is executed instead, but doesn't have any code, so nothing happens.
Or you could code a small piece in there that informs the player this item cannot be used or equipped.

No need to write code yourself to detect the kind of item here, as the correct method is called automatically.


Banshee(Posted 2012) [#8]
Hrm, some valid points, but embedding graphics code in a data class prohibits running it on a daughter thread which is a major drawback if any of the items require significant processing - such as shooting, physics, or multiplayer syncronisation - so I think both approaches have significant flaws - and so you have to choose the method with the flaws you can accept - or find another solution altogether, which requires more thought than i'm capable of right now.

I wouldnt under-estimate the importance of memory efficiency in a project of that nature either, because we're compiling 32bit we only have access to 2gb of RAM - and that is not a bountiful supply if you have a large dataset lingering in memory, and might result in needing to do shuttle loading of map data for instance.

Last edited 2012


zoqfotpik(Posted 2012) [#9]
My application is not going to require much CPU at all but that is a good point about separate control and display classes. I will have to look into that further. Overall this is a much thornier problem than it appears to be. I think I will end up getting it working with loading data from files and instantiating prototypes from there, then have the actual items in inventory be flyweights of those protos.

This application is not like StarCon but it so happens that I will be releasing a StarCon-like game before I start serious work on the one I am talking about here. I know RPGs are hard so I am gathering thoughts and ideas before I jump in, and prototyping subsystems.


blackwater(Posted 2012) [#10]
Maybe this small bit of code will help you out or give you some new ideas. I have an item type that has fields for every possible bit of info that I need on that item. When I create a new item, I call the method PopulateRecord and it will fill in all the defaults for that item based on a name.

With that item there are lots of things I can do with it, mostly adding it to a list and sort it. It's also easy to save and load from a text file. I admit I haven't tested this with hundred of items yet but I really don't anticipate a problem with that, blitzmax should be easily able to handle thousands of objects.



Type ItemRecordType
Field Name:String
Field Twohanded:String
Field Health:String
Field Weight:Int
Field SellPrice:Int
Field BuyPrice:Int
Field EquipLocation:String
Field Food:String
Field Drug:String
Field RangeWeapon:String
Field Image:TImage
Field Description:String
Field SingleHanded:String
Field MeleeWeapon:String
Field Ammo:String
Field MinDamage:Int
Field MaxDamage:Int
Field AutoMinDamage:Int
Field AutoMaxDamage:Int
Field MinHealValue:Int
Field MaxHealValue:Int
Field armor:String
Field uses:Int
Field healvalue:Int
Field booze:String
Field Link:TLink
Field inventoryslot:Int
Field BodyLocation:String
Field maynotequip:String
Field Quantity:Int
Field ClipSize:Int
Field Audio:String
Field AutoAudio:String
Field AmmoType:String
Field AutoMode:String
Field AutoAmmoUse:Int ' how much ammo the weapon will use if it's firing in auto mode
Field ItemHealth:Int
Field SkillNeeded:String
Field Slot:Int ' where in the inventory this item is
Field VendorName:String ' who does this item belong to if it's for sale
Field VendorSlot:Int ' where is this item in vendor inventory

Method PopulateRecord(ItemName:String)
Select ItemName
Case ItemNamesType.Club
name = ItemNamesType.Club
meleeweapon = True
health = 50
singlehanded = True
weight = 10
sellprice = 50
BuyPrice = 50
Description = "club"
equiplocation = "hand"
MinDamage = 3
MaxDamage = 6

** end code tags


Kryzon(Posted 2012) [#11]
If you eventually want your users to modify\add weapons and equipment, you should consider implementing a script system. That is, code that lies outside of your runtime so people are able to contribute even though they don't have your engine's source code.

You can design a script format for declaring items. Ideally, you should design an API to deal with pretty much anything in your game - events, items, GUI, combat, gameplay etc.

Each script sets game-required values and methods for each item definition, but you can declare custom data.
Kinda like a shader language, where you are free to do whatever crazy math and memory operations you want as long as you return a valid pixel color in the end.
In case of your game's items, you'd need to return a valid 'combat damage' value, 'purchase price' value etc. through your item's methods so they behave properly when invoked by the game engine.

You'd preferably use an already-made script system like Lua or Python.
Pseudo Lua:



zoqfotpik(Posted 2012) [#12]
Vey cool and some great ideas.

Not only do I want there to be a script interface, I would ideally like users to be able to connect to the item's computer from within the game... Possibly even through a simulated shell and telnet interface... Wrap your brain around that one.

Is there any sort of python implemented in max or is there any way to bundle a python implementation so that I can have script hooks that connect to scripts running in the python shell?

Last edited 2012


DrDeath(Posted 2012) [#13]
Is there any sort of python implemented in max or is there any way to bundle a python implementation so that I can have script hooks that connect to scripts running in the python shell?

Not Python, but BlitzMax comes with a module to interface it with Lua.


Muttley(Posted 2012) [#14]
You may be better off looking into a component entity system to avoid an inheritance nightmare. See this series of blog posts for a good description of the way they work:

http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

There's another good article here: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

Wiebo has even got a port of the Artemis system for BlitzMax called Artemax you could use: http://code.google.com/p/noisycode/wiki/artemax

Last edited 2012


Kryzon(Posted 2012) [#15]
I was intrigued by the component-oriented system Muttley suggested, and found this at StackExchange; it's a pretty good analogy of how it works:

http://gamedev.stackexchange.com/a/31491

The goal of using a system like this is, as discussed, "to avoid an inheritance nightmare".
You can still use inheritance, mind you; but using a component-based system can help you get rid of whatever unnecessary inheritage you'd get with classic OOP.
This system is also best used in large projects, with potentially a large amount of different entities (like an MMOG).

You could use user-types to define your components in BlitzMax.
Then an entity would be something like a very simple user-type with nothing but an ID and a list of TComponents:
[bbcode]
Type TEntity
Field id:Int
Field components:TList
End Type[/bbcode]
That's it. Then an instance of such entity would be populated with whatever components are necessary to give it meaning to your game (be this entity a player, a door, an item, a GUI piece etc.).


zoqfotpik(Posted 2012) [#16]
I see. I am thinking the component system is going to be how I will go. The great thing about it is the list can be added to at runtime-- eg. you could allow the players to add components to their weapons themselves, like sights, bayonets, collapsible stocks, etc. If you are going to make a mod-friendly system, isn't it a great idea to expose it to the players within the game?