Classes and Structures. (Win32 Console RPG game) - which type to use?

Basically I am trying to figure out which control structures to use when structuring the following data:

Player data. This is initially determined by two entities: Player's Race and Player's Class. When selecting a Race, varying pre-determined base values will be set to determine things like HP, MP, damage, etc. Selecting a Class will set your character's level to 1. Each Class and each Race will separately add a varying amount of these stats ON TOP OF the base values for every level-up that the player gains. For example, a Human would start off with 40 max health and gain +4 max health per level up. If this Human is a fighter, he would gain an additional +4 max health per level up. So basically at level 1, a Human Fighter would have 48 max health. Here's the equation for that:

player max hp = 40 base hp + (4 human hp + 4 fighter hp)

Simple algebra. I avoided using code simply to avoid syntax highlighting for the equation itself.

Now I'll share some code so hopefully you can get a better grasp of what I'm trying to do. I will ask questions via //comments, as well as asking additional questions after the following code block:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct player //BASIC (and incomplete) PLAYER CHARACTER STAT RUNDOWN
{
	int lvl; //player's current level. Should this be a constant?
	int lvlexp; //experience points needed for player to level up. Constant?
	int currentexp; //player's current experience points. Constant?
	int maxhp; //player's maximum hit points
	int currenthp; //player's current hit points
	int maxmp; //player's maximum magic points
        int currentmp; //player's current magic points
	int gold; //player's gold. Should this also be a constant?
}
human, dwarf, imp, fighter, rogue, mage; /*Should I make separate structures for Races and Classes?*/

void ifhuman() //BASE STATS FOR HUMAN
{
	std::string race= "Human";
	human.maxhp=40;
	human.currenthp=40;
	human.maxmp=25;
	human.currentmp=25;
	human.gold=12;
}


Now the reason I ask if these should be constants is because I can't figure out how to get this code to compile properly with the following code included:

1
2
3
4
5
6
7
8
9
10
11
void lvlfighter()
{
	std::string clas = "Fighter";
	fighter.lvl = player::lvl+1;
	fighter.lvlexp = player::lvlexp+200;
	fighter.maxhp = player::maxhp+7;
	fighter.currenthp = player::currenthp+7;
	fighter.maxmp = player::maxmp+1;
	fighter.currentmp = player::currentmp+1;
	fighter.gold = player::gold+7;
}


Because of this one glaring error:

error C2597: illegal reference to non-static members:
player::lvl, player::lvlexp, etc.

How do I arrange my struct syntax so that the player's stats can be manipulated via outside (public) functions using only 1 reference in my formulas? Static class variables? Friendship?

I tried dicking around with it in VS 2010 after reading http://www.cplusplus.com/doc/tutorial/classes2/

If anybody could help me, that would be great. I hope my question is straightforward enough. Thanks in advance for any help, it is greatly appreciated.

-Adam
Last edited on
Rather than a function, why not define an additional structure that holds the bonuses a character gains per level up?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct player 
{
	int lvl;
	int lvlexp; 
	int currentexp;
	int maxhp; 
	int currenthp; 
	int maxmp; 
        int currentmp;
	int gold; 
        LEVELBONUS levelBonus;
}

struct LEVELBONUS
{
    int strBonus;
    int intBonus;
   //etc
}

LEVELBONUS addLvlBonus(const LEVELBONUS *bon1, const LEVELBONUS *bon2)
{
LEVELBONUS ret;
ret.strBonus = bon1->strBonus+bon2-strBonus;
//etc
return ret;
}


That way you would just add the levelbonuses one gets from a certain race and class combination.

Of course, for nonlinear level bonuses (level 1 +2str, level 2 +4str, level3 + 5str etc) an object oriented model would probably be better (maybe with the decorator pattern).
Last edited on
In doing what you suggested, where exactly do I list object names? Do I list them twice, once after player member names and once after LEVELBONUS member names?

Also, where do I specify all 3 object's (Race's) values and all 3 object's (Class') values? This is what confuses me because the tutorials are convoluted and filled with other things that I'm not fully familiar with. Is that what you are referring to with bon1, bon2, etc?

Bit of extra info for you:
LEVELBONUSes are linear while experience levels are non-linear. Not sure how this factors into the structure of everything. I also plan on adding much more data, such as different attacks and spells. I want to tackle this + character generation first though, so I would like to know if there is an optimal way to structure everything if I am expecting heavy data updates when said data updates also depend on character's Race and Class.

Forgive the noobishness, but I am < 2 weeks into computer programming.

Edit:

Thank you, by the way, for that great knowledge. I really wish I had an IDE at work so I could double dip and toy around with this. Right now it's just google and these forums to further enrich my knowledge. >.<
Last edited on
The idea behind this that you'd define a LEVELBONUS for each class, and one for each race. That way you only have to deal with number_of_classes+number_of_races cases, instead of with number_of_classes*number_of_races.

Basically, instead of doing something like this:
1
2
3
4
struct HumanFighter
{
//Attributes
};


You'd do something like this:
 
hero.levelBonus = addLvlBonus(&HumanLevelBonus, &FighterLevelBonus);


On a side note: Do you really think it's a good idea to get started on an rpg with 2 weeks of programming experience? I have >4 years (still little compared to some of the others here), and I would still consider a RPG a quite big and difficult project.
Exactly what you just described is what I planned on doing to begin with, only using functions instead of a structure hierarchy. (Structure hierarchy is better now that I see the scope of it.)

My plan is to have the player's data structured the way you suggested, and then have separate 'monster' data in a completely different structure/hierarchy. Basically I would want to be able, for example, to reference 5 different types of monsters to engage in combat with simultaneously, all with randomly generated stats (within their limits). Would I be able to just define another structure inside struct player for this, or would my best route in terms of organization and degree of difference be to just define an entirely new structure for monster entities? In testing, I will be starting with just 1 monster type and going from there, and would like it to be relatively easy to just add data and re-build.

@ the side note. I am pretty sure that I am picking up very quickly on C++ concept and theory. I am writing programs right now that my friends were writing 6 months into college, and I don't say that to sound cocky or anything, just that I "get it". Some people learn a lot faster than others. On top of that, this RPG is a console app, so I won't really be worrying too much about GUI, graphics, or appearances other than ASCII art. At least for v1.0.

Thank you for further explaining this.
Last edited on
Basically, you can use the same structure for monsters as for characters. However, monsters have a few additional features (for example, the experience they give when they die), but for example can't level up (at least in most rpgs), so they wouldn't need the LEVELBONUS structure.

So what you could do is another structure reorganization:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct Actor
{
//common traits between Monsters and Players
};

struct Player
{
Actor actorData;
//Player specific data
};

struct Monster
{
Actor actorData;
//Monster specific data
};


That way you can treat monsters and players the same way (actorData should hold data like HP, MP, Strength etc) in a fight. Makes the whole thing a lot simpler (at least in my opinion), cause you can just do something like that:

 
void attack(Actor *left, Actor *right);

Which would enable you to do various interestening things, like for example let monsters fight each other (charm/rage spell anyone?) or let players fight each other (some sort of 2 player vs mode?). Of course you don't HAVE to implement something like that, but this makes it easy to do so. Oh, and also it makes you look smart. (also, think about other possibilities... like summoned creatures who have some sort of timer before they disappear etc).

This is basically sort of object oriented programming, just for now without classes.
Last edited on
Which would enable you to do various interestening things, like for example let monsters fight each other (charm/rage spell anyone?) or let players fight each other (some sort of 2 player vs mode?). Of course you don't HAVE to implement something like that, but this makes it easy to do so. Oh, and also it makes you look smart. (also, think about other possibilities... like summoned creatures who have some sort of timer before they disappear etc).


These are the things I had in mind and was looking for proper structure to do so. Thank you very much for this. The only downside to finding all this out at 10 AM is that now I have to wait until 5:30 to start re-compiling and re-building code!!! AHHHHH!!! (Yeah, today is going to go by slow.)

So this would let me add a nested structure to struct Actor, for example, to add a Boss database? And I'm nowhere near this step yet, but what about another, separate item database? Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
struct gearItem
{
int gearItem dmg;
int gearItem crit;
int gearItem armor;
//etc...
UNIQUEITEMS uni;
PREF pref;
SUF suf;
}
sword, shield;

struct UNIQUEITEMS
{
int dmg;
int crit;
int armor;
//etc...
}
theGrandfather, stormshield; //(Diablo 2 reference herp derp derp :P)

struct PREF; //Item prefixes
{
int dmg;
int crit;
int armor;
//etc...
}
sharp, jagged, dull, rusty

struct SUF; //Item suffixes
{
int dmg;
int crit;
int armor;
//etc...
}
ofpain, offire, ofcutting;

struct consumables
{
int currenthp
int currentmp
int attackspeed
}
pot1, pot2, pot3; //(potions) 


Or something like that?
Last edited on
Topic archived. No new replies allowed.