   Class design RPG?
  Hi all,I'm new to C++ and object orientation (well I did some stuff in ADA some years ago but with time and enough alcohol I manage to forget it all (almost)).Anyway I always wanted to learn C (or later C++) but in school they always forced me to learn other languages so I thought I would get into C++ when I had more time. Now with a 10h/day job, a house, gf and 3 dogs I realize I will most likely never have more time so I decided to learn little now and then on my lunchbreaks or if I get the time in the evenings. I started with this tutorial:http://www.cplusplus.com/doc/tutorial/I can really recommend it for those that are new to c++. Very easy to follow.I think i got atleast some of the basics (like how to make loops and stuff, I'm beginning to understand pointers (totally new to me) and I get some flashbacks from school when my ADA teacher talked about classes and objects...Well enough about me and lets get down to bussiness.I'm trying to figure out how to make "good" classes.I understand simple things likebaseclass shapederived class circle(circle is a shape) and I can get it right if I "cheat" a little and look in the tutorial now and then. But now I want to make more advanced classes and as a practice I thought I make classes for a very simple RPG. I'll go trough the basics below:I want to have3 types of creatures that either the player can be or the npcs/mobsHuman, Dwarf, ElfI want to have 3 professions that is shared for all the creaturesWarrior, Thief, MageAnd for practice I want a 4th profession thats only available for Human.Each creature type should have some stats, hitpoints/mana, and what weapons/magic they can use. Strength, Dexterity, Endurance, Intelligence, Wisdom.Hitpoints, Mana (+from equipped armour/weapon attack/armour)(For practice the Elf Mage will have another stat called Willpower)All creatures will have 3 armour slots: Leg, Body, Headand 2 weapon slots: R-Hand, L-HandI will have 2 weapon types and 2 magic schoolsSlashBluntDestructive magicRestorative magicThe weapon types will be divided into 1-h and 2-h weapons.Slash will also be divided into Sword and AxeBlunt will be divided into Mace and StaffDestructive magic will have 2 schools Fire and Ice Restorative magic will have 2 schools Spirit and NatureThe weapons should be able to modify stats on equip and ofcourse deal damage on hit.The destructive spells should be able to temporarily modify a stat (like weaken -5 str for 3 turns)The restorative spells should be able to increase one or more stat/s for x turns.My question is: what is the colour of my mouse?Sorry I couldn't resist ^^ got a wierd sense of humour :) No the question is how would I set up this class structure, which classes should be derived from others, do I need aditionally (helper) classes (reading the other post about RPG on this page indicates I might need a modifyer helpclass (I didn't completly get it so I have to reread that post later).Lets start with the creature/profession.Should I have a baseclass Human and then derive professions from it like HumanWarrior/HumanThief/HumanMageThinking that class Human will have some parameters (Strength, Dexterity, Endurance, Intelligence, Wisdom, Hitpoints, Mana (+from equipped armour/weapon attack/armour) and then perhaps (in the far away future) special human graphics, rules that apply to humans like different resists, movement speed and so on..and then adding(deriving) for example warrior to the human class where the warrior class will modify stats (+ str, - int..) add what weapontypes a warrior can use, perhaps add some special rules that only apply to warriors (like can wear platemail, if so cannot swim). Speaking of swimming... each profession should add some skills like blocking, dodging....Anyway wouldnt I end up with a derived class with tons of parameters (and from what I understood so far you should if possible try to keep the number of parameters down for your classes or you will end up with classes that are hard to use).How about weapons should I make sort of this class structure:Slash    -1h   -sword  -axe  (-dagger)    -2h  -sword  -axeBecause for example the dagger is a 1-h weapon which is slash damage (this would imply that a dagger is derived from a 1h weaponclass that is a slash)How will I treat equip/wield... should the (derived?)class, say, dagger check if the class HumanThief have a free handslot or should I have a helper class for this and if so how would it be constructed? How will this (magic +5str, +3dex) dagger modify the owners stats.. When creating 3 magic daggers I want the first to have 10dps add+5 strthe second is a mage dagger 8dps add +5int and +3wisdomthe third dagger is tricky it will add +8 willpower (which only the elf mage have, what happens if a human warrior picks it up.. he doesnt have the stat willpower).Any suggestions of what classes I should use (and how they are related to eachother) and what functions/variables should belong to each class???You don't have to write the code more like pseudocode likehumanmage stats x, y, z,.... function for checking if armour trying to be equipped isCloth, function for ... ? O.oAny help is appriciated. Also I usually have very little sparetime (se beginning of post) so I don't have much time browsing trough posts to find pieces of information and then puzzle them together but If You have a good post/tutorial/classdesign tips... I would greatly apriciate if You could link the page and I can read up when I got the time. Does anyone know of an opensourcecode for a basic rpg so I can study their structure or even better a tutorial (even tips about good books regarding class structures/game engines is welcomed)Thanks to all who helps out./edit: I forgot to ask about virtual functions, since all objects will be a creature + a profession should I make the class human completly virtual (or what its called..forgot the name... i mean only contain functions: void func() =0If so I could use a human pointer to point at all subclasses right (but on the other hand I must include all functions of the subclasses as virtual functions in human... or did I misunderstand the entire thing?) /edit/Edit again: Well I think I will go ahead and answer one of my own questions:Probably the professions should be its own class like class warriorand then I can combine them with the creature classes so the class humanwarrior would inherit from both class human and class warrior correctimundo?[Edited by - Hybris on May 27, 2009 5:28:34 AM]
  In my view the the type of class heirarchy you propose is horrible and unneccessary.  You often see introductions to OOP that focus on the conceptual modelling aspect, so it's natural to want to start by coming up with classes for every entity type in your game that seems conceptually distinct. But to see whether this is really necessary you need to look at the actual behaviour and dependencies of your entities.Having a new class for every weapon type in particular seems completely wrong. Think about how the weapons actually behave and what data is needed to define them. Usually there would be:-Type, used to see what skill it relates to and who can equip it.-Range- Damage type-Damage amount or rangeThis defines a weapon template, individual weapons would also have a text description, some properties and bonuses. If this is all there is then the differences between weapons is clearly something that can be defined by the data within a class, tings like damage type can just be an enumeration and then creating a new weapon type is just a matter of creating a new file in the appropriate format, without having to touch your code.In fact whenever your think about an inheritance heirarchy you should consider whether there is a simpler approach using data driven methods and composition. By composition I mean that your base generic class gains new functionality and defintion by owning other classes rather than inheriting from them.Races are a possible example, instead of creating a new class every time you want to add a new race have a Race class and something like a "Feat" class along with it. The Feat class contains data specifying an ability, modifier or restriction and your creature has a list of feats, these feats can be added form anywhere in principle, some will likely come from their class and level up choices, but some can come from their race.  Then when you want to create a new race you need to edit the file that specifies what feats are associated with it.   ;  There are various ways you can set this up. The range can go from a class each for every possible race-profession combination (ok, this would be really unwieldy and is only an exageration), to a Player class which supports any kind of character, to (on the other extreme) simply an integer (used as an id in various managers to get access to an entity's components). Generally, if two classes behave the same or very similarly, there's not much point in making them separate (the willpower you could do by either giving it to everyone or by having the attribute list be flexible instead of hardcoded). I think the easiest to start with is just making one class for this, either a "Player" class or even more generally an "Actor" class which can be controlled by either the player or the AI. Then you can load the actual race/profession/inventory/equipment/mesh/image/etc data from a data file. This has the advantage that it's also easier to add new races, items, etc. Same idea for items - they might seem different now, but actually they're all the same. Have just a single "Weapon" class, load them from file, have some fields for description and the type of damage they do, keep track of what effect they apply, have a boolean perhaps for "two-handed".The color of your mouse is the effect of diffuse scattering and depends on the wavelengths of incident illumination and the surface properties. Unless you have one of those transparent mice that have a LED inside, then it's a bit more complicated. I haven't done this before, but to keep track of the effects of items/spells on an actor's stats, you could use an effect stack (I'm using the word "stack" loosely here, it doesn't have to be a real stack in the programming sense). You will need to update the stack regularly to decrease the "time to live" of timed effects, and you probably also want to let the actor react to various events like putting on or taking off an item by pushing/removing an effect from the stack. To determine the player's actual stats, you would then have to start with the base stat and search the stack for all effects affecting that stat, then add them all up.   ;  Okay, some brainstorming ^^enum eStatType = { STAT_STR, STAT_WIL, ..., STAT_MAX };enum ItemClass = { CREATURE, WEAPON, STATICOBJECT, ARMOR, ...)enum WeaponSubClass = { WEAPON_1H, WEAPON_2H, enum CreatureEquipSlot = { EQ_LEFT = 1, EQ_RIGHT = 2, EQ_HEAD = 4, EQ_LEG = 8, ... }typedef int ItemType;class WeaponInfo{}class CreatureInfo{  int equipslots_bitflags; // So we can have different equips for different creatures}class TypeInfo{  // ItemType  (for lookup in the typemgr)  // ItemClass (for every enum-value, we have 1 c++ class)  // WeaponInfo* (only valid for weapons  // CreatureInfo* (only valid for creatures containing eg Race (Elf, Orc, ...)  // ...  // Texture, Model, ... };exampleItemType 1, ItemClass = Creature, CreatureInfo.equipslot_bits = 5, WeaponInfo = NULL etc for all your items/creatures/possible objects (more or less one entry, for every 3d-model you have). class TypeMgr // singleton ({   // only const-members, no functions which modify data (except on init)   vector <TypeInfo> types;   bool initializeFromFile (... ) { ... }// query    bool isCreature (ItemType _t) { return types[_t].ItemClass==CLASS_CREATURE; }};class ObjectMgr // could be a singleton{  // Manage Entity-instances  vector <Entity*> objects;  UniqueId Create ( ItemType _t, _initInfo );  bool Destroy (UniqueID _id);  Entity* get (UniqueID _id); };struct stat{  eStatType type;  int value};class Entity{  Position pos; };class Creature: public Entity{  // flyweight pattern, keep the class small & lookup shared   // info between Creature-Instances in the typeManager  ItemType type;  vector <Stat> stats;  vector <Bonus> static_boni;  vector <Bonus> dynamic_boni;  // need some calc to get totals, probably caching is a good idea ^^};// Note: You might want to differ between Hero & NPC (both deriving from// creature), since are probably very different (eg AI vs player-directed, // maybe some hero-only values like uncovered map / fog-of war (big, no need to store for all creatures)enum eBonusType = {  BT_SLASH_DAMAGE,  BT_XXX_DAMAGE,  BT_DAMAGE_OVER_TIME_PHYS, };class Bonus{   eBonusType type;   bool  hasLifeTime; // when false, ignore lifetime   float lifetime;    // when <=0.0, remove/expired   int   value;  // bonus value};class Weapon{  vector<Bonus> static_boni; // bonus of weapon, always there  vector<Bonus> dynamic_boni; // on hit, transfer these to creature (eg dot-damage, or maybe even a healing-spell)};Just my 2 ct :)   ;Quote:Original post by Kitt3nOkay, some brainstorming ^^And the ugly singleton rears its head... Don't go teaching that highly controversial design pattern to new people. :-D Though I guess you didn't really, since you've only hinted at it.   ;  I'd also wonder whether this is the right thing to be worrying about if your just starting out in RPG programming. Most of those questions seem to be about mking things configurable, i.e with different types of weapon, class etc.I would start out by just trying to get a generic Actor class to be able to do the set of primitive actions you want your game entities to be capable of. Get them to walk, navigate, percieve each other, cast a simple spell and attack each other.  This will give you a better idea of the set of properties that need to be configured to define the range of entities you need.The code will likely need some refactoring, but that can't be avoided generally when starting out.;  Hello Hybris, good to know that you want to get into the fascinating world of game development...It is very easy to get with OOP; you just need to learn some "rules" and you will be ok.First, good job with your high level design; it is an important stage before coding anything even if you are learning, you will learn there are more than ideas, after writing down a high level design like this start making question to yourself, like "If I said all creatures should have this, why I don't create a generic class that share this?" and that's what I'll try to explain to you based in your questions and design.This is by not mean the ultimate class design for a RPG game but it will help you to get the idea.I'll not use any specific language.First we need an abstract class Character... We need it to be abstract (pure virtual if you like it) because we don't want to instantiate a Character but inherit from it, imagine yourself playing WoW (or put your favorite game here) and telling everyone "I have a really good Character, I can beat everyone in my server... baby I'm god... I know, I know... and then someone ask you, yeah but what is your character class (profession)? You see? You can't answer that question because your character is a character! But nothing more and that's why you can't play as a generic character so you need to choose a profession!. Ok I think you got the idea... So our class Character is just telling us what a character should have but is not giving us any information about its behavior, and that's why we need specific classes to inherit from it. //A very generic class (based on your design)Class Character{//You will find that every attribute listed in this class is shared by all creatures in your game (based in your design of course)//Basic stuff, these can be integers, is your choise.hitPoints;mana; //Stats should be integers.strength;endurance;dexterity;intelligence;wisdom; /*I feel that race should be here, I know you want to practice but you will learn that create hundreds of classes won't help, the best you can learn is to create very specific classes and not to repeat code */race;  //(can be an integer, but I feel it's better an enum here)/*If you feel that a profession can't block or dodge set these to zero, but keep it here, why? What if a magic from a mage increase it on a creature without this attribute?  As a player I expect it to work. These two attributes should be doubles*/ dodge;block;//Armor slots should be an Armor object. I'll explain it later.armorSlotLeg;armorSlotBody;armorSlotHead;//Weapon slots should be Weapon objects. I'll explain it later.weaponSlotRight;weaponSlotLeft;/*Very powerful code omitted*/}Ok now we have our blueprint, our conviction of a Character, but it is useless! We want it to fight, run, and kill everything that is in our way! That's why we will create more specific classes and here is when you realize that you need to inherit and why...Lets say you want a Warrior to perform a special ability with a slash or a blunt but you don't want a mage doing it, you want a Mage having a spell book as a class attribute but not a thief, and finally you want a Thief with a special class attribute called noiseMeter, even more you want to make sure that every time someone choose a Warrior it will create a Warrior and not a Mage, What I'm telling you are some of hundreds of reasons that will let you know when to inherit, as you can see now we can create hundreds or thousand of professions (ok that's a lot of brainstorming) without repeating the same stats over and over since we inherit it from the parent of all the mystical creatures in our fantasy world, the Character class.Now that we have our professions, you can pass the race in the constructor of it. That is let's say you want a Warrior, when you are going to instantiate a Warrior object you most provide the race in the constructor (assuming you code that constructor of course) if you want to perform some conditions for a specific profession, "The Humans are the only able to be Mages" then you can do it in another part of your program, for example a menu, the player chose a Dwarf then the player can't see the profession mage in the profession selection menu.Now that you got the constructor idea (I hope) you can have another profession for the Human race only as you asked.For the Elf Mage that you asked to have willpower, you could create a profession ElfMage, inherit from Character (as always) and add the attribute willpower to it. Because you know that an Elf Mage can only be an Elf, duh... you don't need to pass the race attribute in its constructor.More about constructors... constructors are the best place in your very specific class, a profession in this case to initialize all the attributes from it and those that it inherits from Character. That is, a Warrior can have different starting stats than a Thief. But since it is a RPG game maybe an Elf has different race attributes than a Dwarf, that's why I consider that you should implement (code) a method (function) in your specific profession class that initializes all the character stats (and specific class attributes) based on conditions: If (human) then {strength = 6...} Else if (dwarf) then {strength = 8...} I think this is all with initialization stuff. One more thing you can and should declare this method in the Character class because you will notice that every profession or creature class will share it. ## I'll continue a bit later with this answer, I have to go right now, If you have problems to understand something in this stuff I wrote please ask me, I'll be happy to help you ##[Edited by - maldithul on May 28, 2009 6:58:55 AM];  Hi, wow now I got something to think of. Thanks to all for Your input.As I said I'm still pretty new to object orientation so maby I "overuse" the class concept (sometimes I do it a little on purpose to get the hang of how it works like inheritance and things like that.When I programmed before mainly in basic I used to have say integer values to represent lot of stuff and the code worked but it was pretty ugly and if you were going to change something some weeks later it was... well it took some time to remember what was what :)I thought maby if I did classes of "everything" it would be easier to follow later. But I realize I shouldn't have too many different classes either because then I might get lost which class did what...Anyway I got hit by a truckful of work so I won't have time to work with the tips and ideas You posted for a few days but when I had some time to figure the posts above ^^ out I will bump this thread with some new questions.Thanks once again for helping me out.   