RPG equipment

How are these things done in the great games?

I can think of a few solutions, but i’m just wondering how they do it.

And how it can be done in blender?

So how does equipment like: armour, helmets, boots, and, … get added and deleted when equipped?

Do you have a base mesh and add in objects to it?
Do you make a coherent character out of pieces and bits?
Does it work on one armature?
Do parts of the mesh get deleted, masked when others are added in?

So please enlighten the naive and not knowing.

How are these things done in the great games?

depends on the game. in all cases you need a database to store the items of the inventory, and one for all the items to get the values of each one. some games combine this with random items, that combine words, stats and descriptions from databases. databases can be any form of data structure that you can store in memory or disk: dictionaries, lists, xml files, and others. each items would have fields with things like: name, attack, defense, description, effects, image to use, etc.

And how it can be done in blender?

i’ve done inventory systems in blender, but you HAVE to know python. one method was creating a txt file with all the objects and then using the python “Open” function and going to the line of the object and the next 10 or so lines for the fields. this was really strict, so i looked at other ways to do it. the one i’m looking at now is using an xml file and DOM or other python method to read it and it’s fields.
once you get the data, you can use it to write the description into a menu, save the stats in the inventory dictionary, and access them for calculations of damage, etc.

So how does equipment like: armour, helmets, boots, and, … get added and deleted when equipped?

there is a slot, a variable or dictionary that contains the information of the equipped item, you would have different types of slots: head, body, weapon, etc. first you check if the slot is being used, for this you use an “empty” object every time you unequip an item. when you swap you just replace the data of one item with another.

Do you have a base mesh and add in objects to it?

in skyrim there is a base object that they add items like armor over it. other games replace the mesh with one with armor on it, where the body is cut to only show parts that will be seen during the game. this method is more efficient, but you need a mesh for each armor. hair can also be replaced with a helmet.

Does it work on one armature?

yes.

Do parts of the mesh get deleted, masked when others are added in?

you have all the meshes on a different layer, and all the objects on the character, and then use replaceMesh on them to equip, and when you unequip, it is replaced with an invisible or concealed mesh.

thx for the fast reply!

In general: separate the game model (which is not the mesh ;)) from representation.

Example:
your character could be model like that:

  • it has 150 maximum health
  • it has 100 health
  • it has 1.5 health regeneration per second
  • wears an item A (with 20 armor)
  • wears cloth B that provides 10 magic resist
  • it has a shield of strength 10

All this attributes and values describe the current status of the character.
You can easily change the values according to the business rules of your game. E.g. after a second health is 101.5 (due to the health regeneration)
None of the are visible to the audience (The games business should work without them). This is the game’s business model -> short: model.

But you need to interact with the audience. To do so you create a representation layer -> short: view.

The view checks the model and creates a representation of the current state. When your character has 100 health of 150 max, the life bar should show 2/3 of the maximum. When the character (model) wears an item, the view shows a representation of that item. The same with cloth, weapons and so on.

This means you (as audience) see a breast plate because the character wear a breast plate rather than the other way around.

The view provides interaction between player and the model. E.g. when the player clicks a point on ground it can act as input to the model (character should go to this clicked location). The view does not care how the model does that, it just submits the request.

Finally this makes a pretty efficient system. Imagine your game has 2000 characters. All you need to describe a character is a bunch of attributes and values. But you only need to show the few characters that are in view of the camera.

I hope it helps a bit.

I have icons and models that have the same properties in different scenes…moving an icon to an equipment slot simply spawn the corresponding item into the main scene…and clicking an a ‘pick up’ object spawns the icon…this is just how I do it, because it is relatively straight forward…in any case it takes some planning to make a decent equipment system…mine is feature complete…but I may need to tweak it some before I am finished with my game…maybe even whittle it down…??? who knows :slight_smile:

I do not recommend even attempting it though if you have little to no experience in python…better to start small…or create a system like the old zelda games where there were only pre existing slots specific to pre exsisting items…this could be easily controlled via bricks…a bit messy but do-able.

This is fairly advanced, but here’s how I like to do it. As stated above, Python knowledge is a must for something this complex.

First, I create an external .json file (rename the .txt of your text file to .json, Windows will warn you that this changes the filetype, but this is what you want so do that). I start writing it as a dictionary, and fill it with little dictionaries that make up the items themselves. Here’s an example:

{
"weapons":{
     "magic_sword":{"cost":500, "attack":8, "durability":50, "effect":"shoot_magic"}
     },
"armor":{
     "iron_armor":{"cost":500, "defense":5, "durability":20, "effect":"none"},
     "mage_robes":{"cost":75, "defense":1, "durability":8, "effect":"magic_boost"}
     }
}

In my main game code, I import json at the top of my script (with “import json”), and like this, tell my script to find the file and translate it:

import json

filePath = bge.logic.expandPath("//files/")     # PLEASE NOTE: For this to work, your file needs to be in a folder called "files" in the same directory as your .blend file!!
dict_itemlist = json.load(open(filePath+"itemlist.json", "r"))     # Also note, this assumes the file is called "itemlist.json".

I use json because it directly translates to usable code, without any extra unnecessary steps such as literal_eval, which can glicth fairly easily and takes up a lot of runtime resources.

So, with every project I start up, I have a “setup” script run at runtime that runs any code-required function I need to have happen. In this instance, we need to save this .json file (which is read by the BGE as a dictionary) as a property, so that we can access it from anywhere else at any time.

(Here’s something cool I discovered about Blender object properties: You can save them as ANYTHING. Lists, dictionaries, EVEN OBJECTS THEMSELVES. Try it, it’s REALLY useful!)

So, put an “itemlist” property on whichever object you’d be accessing for this kind of thing (I like to have a central empty called “game_info” to store stuff like this), and in your startup script, simply save the dict into the property like so:


obj_info = bge.logic.getCurrentScene().objects['game_info']
obj_info['itemlist'] = dict_itemlist

Now, you can access this from any other script, anywhere else in your game. Here’s a little example for equipping the player:

dict_itemlist = obj_info['itemlist']
player['currentWeapon'] = dict_itemlist['weapons']['magic_sword']

And WHA-BAM, your sword is equipped. There’s obviously a lot more to do in order to create things like UI and functional equipping methods, but I hope this helps somewhat. :slight_smile:

Looks great. It would be great if you made some video tutorial series - how to set up RPG template with your method.


{
"weapons":{
     "magic_sword":{"cost":500, "attack":8, "durability":50, "effect":"shoot_magic"}
     },
"armor":{
     "iron_armor":{"cost":500, "defense":5, "durability":20, "effect":"none"},
     "mage_robes":{"cost":75, "defense":1, "durability":8, "effect":"magic_boost"}
     }
}

it would be very easy for the player to cheat if you store it in plain text like this.

That’s a great point. I’m still pretty new to how json works, I wonder if there’s a way to pickle it for storage purposes…

you could encrypt it

here is an working example


import ast
import base64
import hashlib

def genhash(val="default"):
    gen = hashlib.md5(val.encode('utf-8'))
    return gen.hexdigest()

def encode(key, clear):
    enc = []
    for i in range(len(clear)):
        key_c = key[i % len(key)]
        enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
        enc.append(enc_c)
    return base64.urlsafe_b64encode("".join(enc).encode()).decode()

def decode(key, enc):
    dec = []
    enc = base64.urlsafe_b64decode(enc).decode()
    for i in range(len(enc)):
        key_c = key[i % len(key)]
        dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
        dec.append(dec_c)
    return "".join(dec)


player = {}
player["stats"] = {"HP":10,"MANA":1}
player["inventory"] = {"1": {"name":"broadsword" , "stats": {"dmg":5,"speed": 20 } } }

passwd = genhash("this is a very very very long pass")

out = encode(passwd,str(player))

print(out,"pass:",passwd)

decoded = ast.literal_eval(decode(passwd,out))

print(decoded)

only the read and write to disc is missing.

The problem with this is the use of ast, versus the use of json. A quick Google search sent me on the right path to correcting my mistake:

https://docs.python.org/2/library/json.html

if you want to use json instead of ast


#encode the dict
encoded = encode(passwd,json.dumps(player))

#decode the dict
decoded = json.loads(decode(passwd,encoded))

Or, if you like SQL, there’s this Python module: https://docs.python.org/3.5/library/sqlite3.html

If you want to write in “binary” data (as in almost direct binary representation) there is the struct module: https://docs.python.org/3/library/struct.html

Now, relative to what the OP asks, it depends on what would float your boat. Meshes surely must be added/deleted/replaced. Either via addObject/endObject or replaceMesh. I don’t know how adding/removing would work without instanciating a new armature each time (can we dynamically bind a mesh to an armature via parenting ?).

For the inventory part you will need Python and some persistance system, now to actually spawn the items in game I would recommend you to run some tests, but you saw it right: either add/end or replace.

That is another good thing about the way I am doing it…it is all embedded in the game…no text file…and it allows for randomizing pickups/drops as well.

Not as far as I know, but I’ve just very recently come up with a solution to this little problem.

Armatures in the BGE can’t change the objects they manipulate in real-time, and the mesh an armature manipulates needs to be a child of it. Knowing this, you can parent multiple objects to an armature, hide them, and use replaceMesh() on a main object. The new mesh can be manipulated by the armature. Here’s the proposed character animation system:

Make one single armature, on an inactive layer, to serve as the armature for ALL of your bipeds. Attach every possible biped model to this armature. In-game, use run-once scripts to spawn in the armature from a character bounds object, use act_addObject.objectLastCreated to declare the armature object itself, and set it as a child of the particular bounds object. Finally, depending on the character and what model/equipment they use, simply use replaceMesh() to set up the armature’s models to suit the character they represent.

This way, you’re cutting down on the amount of armatures you need, as well as the amount of object copies you need (since you can’t dynamically parent mesh objects to armatures, you’d need a copy of every possible model for every single armature otherwise, which takes up a lot of physical space and creates a really messy object hierarchy).

Then how do you save/load the inventory ? At some point a game will need a persistence system of some sort, and will always end up in a seperate file(s).

You have a valid point…maybe I spoke too soon…I do not save and load inventory…or anything yet…I started work on it and decided that until the game is in a more finished state(when I have all the vars I want to save)then I will work on it more…

but if I ditched the random generation I could theoretically just create objects based on ID’s…they would all need to be premade though and then I would need to link them…ofc then I would have a whole lot of them…and that sounds like a lot of work all by itself.

And again thx, for the replies.
I’ve been following it on my phone…

You gave me some thought on how and where to look.
All that rests now is make something work.

The part for encrypting your data is indeed very handy!
Cause like edderkop says you could edit the file quite easily if you locate it.

Well, encryption is really good at securing data between two people from external parties trying to read their communication.
But in this case, your game is in the hands of the people using it, source code included (Python). So its just a bit more of work you have to put in so that people wanting to have fun editing some save-files also spend a bit more time achieving it (you can try to encrypt and I can try to decrypt it just to prove my point). Because the keys used to encrypt/decrypt will be packed in the .blend anyway.

Encryption on a purely standalone app is kinda silly IMO, don’t waste time on that at first :slight_smile:

save your savegame in a binary file would also prevent the casual cheater from cheating.