dynamic inheritance in item creation?

Started by
8 comments, last by ptanggamez 21 years, 12 months ago
In your typical fantasy world RPG setting, there are many different types of “items” in the world. Some simple examples of these would be containers, weapons, and armor. For each of these classifications, there exists a set of properties that apply. For instance, if an item is a weapon, it needs to have properties and access methods for its damage, delay, what hand it goes in, etc. If its a piece of armor it needs to know its armor value and what body parts it protects..etc I’m having some difficulty in laying out my class structure for these items. Simple single inheritance won’t handle my needs since items can be of multiple classifications. A weapon could be a container for instance. This then suggests some form of multiple inheritance, but even that won’t suffice since all combinations would have to be defined. Ideally I’d like to be able to create a item on the fly and add properties/functionality to them based on the combination of types it is. There should be nothing stopping me from creating a sword that has a defensive value and can contain magical gems. Any clever suggestions on how to design this? [edited by - ptanggamez on April 17, 2002 8:32:22 PM]
Advertisement
just create one item-type with a lot of setable parameters.. and everyone with some generic functions like use.. armor using means saving, weapon using means shooting.. and what it does is defined with help of the parameters only..

that way you can simply create a nice editor to set the parameters and load a list of items.. or some script-language..

goldnugged {
type = money
value = 1
}

and in your

item::use() {
switch(type) {
case money:
current_chat_partner->pay(value);
break;
}
}

not that objectoriented but simple and very fast to add all your needs..
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia

My Page davepermen.net | My Music on Bandcamp and on Soundcloud

Not really what I was hoping for.

I don''t want to simply "use" properties all the time. I may need to recall their values to be used externally in some other object.

Can anyone recommend a solid object oriented design pattern that might help me out?
There is a nice design pattern for that. It is called the "player-role pattern".

The player is the object that will take on several roles. For example, in your problem,

thePlayer = Sword

Roles = Could be a set of : Magical, Normal

thePlayer simply contains the list of roles it needs. Roles, can also means attribute or whatever else.

The key is the interface, so for the role above :


    //abstract class for StatusRoleclass StatusRole{ public:         virtual int CalculateDefenseBonus() = 0;         virtual int CalculateAttackBonus() = 0;};class MagicalStatus:public StatusRole{  // ... whatever implementation you need.};class NormalStatus:public StatusRole{   //whatever implementation you need};class WeaponBase{        void SetStatusRole( StatusRole* role );};class Sword:public WeaponBase{ // ... whatever you want.};    


So that's how it works.

An object can have mutiple types of roles and multiple roles of the same type.

Remember, roles really mean attribute
So our Weapon class could also have a role called WeaponQuality that says if the weapon is VerySharp, NoSharp, etc. This WeaponQuality would also have a function CalculateAttackBonus(); CalculateDefenseBonus().

So now our Weapons simply need to add AttackBonus or DefenseBonus of the 2 roles( StatusRole, WeaponQualityRole ) to know the attack bonus or defense bonus.


If the Role ever needs information from the item, well then you only need to pass the object pointer through the constructor or whatever other means.

[edited by - Gorg on April 17, 2002 8:16:34 PM]
I think it the most flexible approach is simply to have an item with a dynamic array of attributes. That way, the base class is

class Item
{
vector Attributes
}

Then each attribute has an id, and data sections. Or, if you don''t mind all the new/deleting you could have attributes of different object types, and store their pointers in the vector.
The player role syntax is has flexible and you don''t need to worry about attribute ids and make sure you are working with the correct attributes and doing all the ugly housekeeping and the casting you need when you have of a data section.
That pattern seems to be a bit limited... it might be adequate for calculating stats or whatever, but I think the original poster is after a little more than just being able to total up a set of bonuses. To use that pattern to meet the original poster''s needs would require so many virtual functions in the StatusRole class that it would be unwieldy, no?

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions ]
I read his post again and you are right, my answer is not what he is looking for.

Well, I still think the pattern is correct, but the rest is wrong.

Just on the top of my head, I would do it like that :

There would a base Item class. Weapon, Armor, Container would simply be attributes(roles) of the item class. In our case it would simply be 3 hierarchy of roles. I am sure he has more attributes, the trick is to regroup them in a role class to minize the number of roles classes.

So an item is only defined by it''s type(application specific. It is the derived class of item) and it''s attribute which are the roles.

So with my idea, if you want a sword to have armor attributes, you simply add an armor role to the class. If you don''t need the armor roles, you set it to NULL or whatever other way you could have to say that it is not there.
I think I would just use some sort of property hierarchy and implement it as a kind of semantic net. That gives you all the freedom you like with your properties, although it's not so useful for the type-specific methods.

So, my advice would be this:
If you can get away with just using properties, just have a map of property names to property values. Property values can be strings and can contain numbers or text, and the way you interpret that depends on the property name. (So the property "name" would treat the value as a string, but the property "age" would pass the string value to atoi() first.)

But if you need methods, you're probably going to have to combine everything into a single class. If you're careful you won't need many functions. For example, each Object could contain a pointer to a list of objects. If this pointer is NULL, then the Object is not a container. If you want the Object to become a container, make that pointer point to a newly-allocated list of Objects. This only incurs a size cost of 1 pointer for all the non-container objects. Other considerations can be done in this way. (I think this is the sort of thing Gorg was saying.)

[ MSVC Fixes | STL | SDL | Game AI | Sockets | C++ Faq Lite | Boost | Asking Questions ]

[edited by - Kylotan on April 20, 2002 10:35:50 AM]
quote:Original post by Kylotan
To use that pattern to meet the original poster''s needs would require so many virtual functions in the StatusRole class that it would be unwieldy, no?

> Wield sword.
The virtual sword is unwieldy.

This topic is closed to new replies.

Advertisement